summaryrefslogtreecommitdiff
path: root/utility
diff options
context:
space:
mode:
authorYuxin Zhou <[email protected]>2021-10-14 00:51:26 +0000
committerYuxin Zhou <[email protected]>2021-10-14 00:51:26 +0000
commit1af8404c54f9c8d3caa2ac3523c2a5f014aecb1c (patch)
tree93e4f4d64ec8c21c01b77f19b8e7326e85227e3d /utility
parent215df45d4b59d4ce8606a88f566d1d426e64a84c (diff)
Release 6.1.9
Diffstat (limited to 'utility')
-rw-r--r--utility/benchmarks/thread_metric/thread_metric_readme.txt227
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_basic_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_cooperative_scheduling_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_preemption_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_memory_allocation_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_message_processing_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_preemptive_scheduling_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/threadx_tm_synchronization_test_example.c29
-rw-r--r--utility/benchmarks/thread_metric/threadx_example/tm_porting_layer_threadx.c401
-rw-r--r--utility/benchmarks/thread_metric/tm_api.h102
-rw-r--r--utility/benchmarks/thread_metric/tm_basic_processing_test.c176
-rw-r--r--utility/benchmarks/thread_metric/tm_cooperative_scheduling_test.c251
-rw-r--r--utility/benchmarks/thread_metric/tm_interrupt_preemption_processing_test.c213
-rw-r--r--utility/benchmarks/thread_metric/tm_interrupt_processing_test.c208
-rw-r--r--utility/benchmarks/thread_metric/tm_memory_allocation_test.c164
-rw-r--r--utility/benchmarks/thread_metric/tm_message_processing_test.c170
-rw-r--r--utility/benchmarks/thread_metric/tm_porting_layer.h48
-rw-r--r--utility/benchmarks/thread_metric/tm_porting_layer_template.c153
-rw-r--r--utility/benchmarks/thread_metric/tm_preemptive_scheduling_test.c270
-rw-r--r--utility/benchmarks/thread_metric/tm_synchronization_processing_test.c161
-rw-r--r--utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c7
22 files changed, 2781 insertions, 2 deletions
diff --git a/utility/benchmarks/thread_metric/thread_metric_readme.txt b/utility/benchmarks/thread_metric/thread_metric_readme.txt
new file mode 100644
index 00000000..70896efb
--- /dev/null
+++ b/utility/benchmarks/thread_metric/thread_metric_readme.txt
@@ -0,0 +1,227 @@
+ Thread-Metric RTOS Test Suite
+
+
+1. Thread-Metric Test Suite
+
+The Thread-Metric test suite consists of 8 distinct RTOS
+tests that are designed to highlight commonly used aspects
+of an RTOS. The test measures the total number of RTOS events
+that can be processed during a specific timer interval. A 30
+second time interval is recommended.
+
+1.1. Basic Processing Test
+
+This is the baseline test consisting of a single thread. This
+should execute the same on every operating system. Test values
+from testing with different RTOS products should be scaled
+relative to the difference between the values of this test.
+
+1.2. Cooperative Scheduling Test
+
+This test consists of 5 threads created at the same priority that
+voluntarily release control to each other in a round-robin fashion.
+Each thread will increment its run counter and then relinquish to
+the next thread. At the end of the test the counters will be verified
+to make sure they are valid (should all be within 1 of the same
+value). If valid, the numbers will be summed and presented as the
+result of the cooperative scheduling test.
+
+1.3. Preemptive Scheduling Test
+
+This test consists of 5 threads that each have a unique priority.
+In this test, all threads except the lowest priority thread are
+left in a suspended state. The lowest priority thread will resume
+the next highest priority thread. That thread will resume the
+next highest priority thread and so on until the highest priority
+thread executes. Each thread will increment its run count and then
+call thread suspend. Eventually the processing will return to the
+lowest priority thread, which is still in the middle of the thread
+resume call. Once processing returns to the lowest priority thread,
+it will increment its run counter and once again resume the next
+highest priority thread - starting the whole process over once again.
+
+1.4. Interrupt Processing Test
+
+This test consists of a single thread. The thread will cause an
+interrupt (typically implemented as a trap), which will result in
+a call to the interrupt handler. The interrupt handler will
+increment a counter and then post to a semaphore. After the
+interrupt handler completes, processing returns to the test
+thread that initiated the interrupt. The thread then retrieves
+the semaphore set by the interrupt handler, increments a counter
+and then generates another interrupt.
+
+1.5. Interrupt Preemption Processing Test
+
+This test is similar to the previous interrupt test. The big
+difference is the interrupt handler in this test resumes a
+higher priority thread, which causes thread preemption.
+
+1.6. Message Processing Test
+
+This test consists of a thread sending a 16 byte message to a
+queue and retrieving the same 16 byte message from the queue.
+After the send/receive sequence is complete, the thread will
+increment its run counter.
+
+1.4. Synchronization Processing Test
+
+This test consists of a thread getting a semaphore and then
+immediately releasing it. After the get/put cycle completes,
+the thread will increment its run counter.
+
+1.5. RTOS Memory allocation
+
+This test consists of a thread allocating a 128-byte block and
+releasing the same block. After the block is released, the thread
+will increment its run counter.
+
+
+2. Thread-Metric Source Code
+
+The Thread-Metric source code may be freely used, providing its use
+complies with the stated copyright banner in each source file. For
+simplicity, each test is defined in its own file. Furthermore, each
+test is written in a generic C fashion. Providing the RTOS vendor
+completes the porting layer file with calls to its services, the
+tests are ready to run on any RTOS.
+
+The source code to the Thread-Metric test suite is organized into
+the following files:
+
+ File Meaning
+
+tm_api.h API and constants for test suite
+tm_basic_processing_test.c Basic test for determining board
+ processing capabilities
+tm_cooperative_scheduling_test.c Cooperative scheduling test
+tm_preemptive_scheduling_test.c Preemptive scheduling test
+tm_interrupt_processing_test.c No-preemption interrupt processing
+ test
+tm_interrupt_preemption_processing_test.c Interrupt preemption processing
+ test
+tm_message_processing_test.c Message exchange processing test
+tm_synchronization_processing_test.c Semaphore get/put processing test
+tm_memory_allocation_test.c Basic memory allocation test
+tm_porting_layer.h Port specific information, including
+ in-line assembly instruction to
+ cause an interrupt for the
+ interrupt processing tests
+tm_porting_layer_template.c Generic template for RTOS porting
+ layer
+tm_porting_layer_threadx.c Specific porting layer source
+ code for ThreadX
+
+2.1 Porting Layer
+
+As for the porting layer defined in tm_porting_layer_template.c, this file contain
+shell services of the generic RTOS services used by the actual tests. The
+shell services provide the mapping between the tests and the underlying RTOS.
+The following generic API's are required to map any RTOS to the performance
+measurement tests:
+
+
+ void tm_initialize(void (*test_initialization_function)(void));
+
+ This function is typically called by the application from its
+ main() function. It is responsible for providing all the RTOS
+ initialization, calling the test initialization function as
+ specified, and then starting the RTOS.
+
+ int tm_thread_create(int thread_id, int priority, void (*entry_function)(void));
+
+ This function creates a thread of the specified priority where 1 is
+ the highest and 16 is the lowest. If successful, TM_SUCCESS
+ returned. If an error occurs, TM_ERROR is returned. The created thread
+ is not started.
+
+ int tm_thread_resume(int thread_id);
+
+ This function resumes the previously created thread specified by
+ thread_id. If successful, a TM_SUCCESS is returned.
+
+ int tm_thread_suspend(int thread_id);
+
+ This function suspend the previously created thread specified by
+ thread_id. If successful, a TM_SUCCESS is returned.
+
+ void tm_thread_relinquish(void);
+
+ This function lets all other threads of same priority execute
+ before the calling thread runs again.
+
+ void tm_thread_sleep(int seconds);
+
+ This function suspends the calling thread for the specified
+ number of seconds.
+
+ int tm_queue_create(int queue_id);
+
+ This function creates a queue with a capacity to hold at least
+ one 16-byte message. If successful, a TM_SUCCESS is returned.
+
+ int tm_queue_send(int queue_id, unsigned long *message_ptr);
+
+ This function sends a message to the previously created queue.
+ If successful, a TM_SUCCESS is returned.
+
+ int tm_queue_receive(int queue_id, unsigned long *message_ptr);
+
+ This function receives a message from the previously created
+ queue. If successful, a TM_SUCCESS is returned.
+
+ int tm_semaphore_create(int semaphore_id);
+
+ This function creates a binary semaphore. If successful, a
+ TM_SUCCESS is returned.
+
+ int tm_semaphore_get(int semaphore_id);
+
+ This function gets the previously created binary semaphore.
+ If successful, a TM_SUCCESS is returned.
+
+ int tm_semaphore_put(int semaphore_id);
+
+ This function puts the previously created binary semaphore.
+ If successful, a TM_SUCCESS is returned.
+
+ int tm_memory_pool_create(int pool_id);
+
+ This function creates a memory pool able to satisfy at least one
+ 128-byte block of memory. If successful, a TM_SUCCESS is returned.
+
+ int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr);
+
+ This function allocates a 128-byte block of memory from the
+ previously created memory pool. If successful, a TM_SUCCESS
+ is returned along with the pointer to the allocated memory
+ in the "memory_ptr" variable.
+
+ int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr);
+
+ This function releases the previously allocated 128-byte block
+ of memory. If successful, a TM_SUCCESS is returned.
+
+
+2.2 Porting Requirements
+
+The following requirements are made in order to ensure fair benchmarks
+are achieved on each RTOS performing the test:
+
+ 1. Time period should be 30 seconds. This will ensure the printf
+ processing in the reporting thread is insignificant.
+
+ 2. The porting layer services are implemented inside of
+ tm_porting_layer_[RTOS].c and NOT as macros.
+
+ 3. The tm_thread_sleep service is implemented by a 10ms RTOS
+ periodic interrupt source.
+
+ 4. Locking regions of the tests and/or the RTOS in cache is
+ not allowed.
+
+ 5. The Interrupt Processing and Interrupt Preemption Processing tests
+ require an instruction that generates an interrupt. Please refer
+ to tm_porting_layer.h for an example implementation.
+
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_basic_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_basic_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_basic_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_cooperative_scheduling_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_cooperative_scheduling_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_cooperative_scheduling_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_preemption_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_preemption_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_preemption_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_interrupt_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_memory_allocation_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_memory_allocation_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_memory_allocation_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_message_processing_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_message_processing_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_message_processing_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_preemptive_scheduling_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_preemptive_scheduling_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_preemptive_scheduling_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/threadx_tm_synchronization_test_example.c b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_synchronization_test_example.c
new file mode 100644
index 00000000..9430d71c
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/threadx_tm_synchronization_test_example.c
@@ -0,0 +1,29 @@
+#include "tx_api.h"
+
+
+/* Define the prototypes for the test entry points. */
+
+void tm_main(void);
+
+
+/* Define main entry point. */
+int main()
+{
+
+ /* Initialize the platform if required. */
+ /* Custom code goes here. */
+
+ /* Enter the ThreadX kernel. */
+ tx_kernel_enter();
+}
+
+
+/* Define what the initial system looks like. */
+
+void tx_application_define(void *first_unused_memory)
+{
+
+ /* Enter the Thread-Metric test main function for initialization and to start the test. */
+ tm_main();
+}
+
diff --git a/utility/benchmarks/thread_metric/threadx_example/tm_porting_layer_threadx.c b/utility/benchmarks/thread_metric/threadx_example/tm_porting_layer_threadx.c
new file mode 100644
index 00000000..4b2e98c0
--- /dev/null
+++ b/utility/benchmarks/thread_metric/threadx_example/tm_porting_layer_threadx.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Porting Layer (ThreadX Example) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/* Turn off ThreadX error checking. */
+
+#ifndef TX_DISABLE_ERROR_CHECKING
+#define TX_DISABLE_ERROR_CHECKING
+#endif
+
+
+/* For smallest size, the ThreadX library and application code should be built
+ with the following options defined (easiest to add in tx_port.h):
+
+#define TX_ENABLE_EXECUTION_CHANGE_NOTIFY
+#define TX_DISABLE_PREEMPTION_THRESHOLD
+#define TX_DISABLE_NOTIFY_CALLBACKS
+#define TX_DISABLE_REDUNDANT_CLEARING
+#define TX_DISABLE_STACK_FILLING
+#define TX_NOT_INTERRUPTABLE
+#define TX_TIMER_PROCESS_IN_ISR
+
+ For the fastest performance, these additional options should also be used:
+
+#define TX_REACTIVATE_INLINE
+#define TX_INLINE_THREAD_RESUME_SUSPEND
+
+*/
+
+
+
+/* Include necessary files. */
+
+#include "tx_api.h"
+#include "tm_api.h"
+
+
+/* Define ThreadX mapping constants. */
+
+#define TM_THREADX_MAX_THREADS 10
+#define TM_THREADX_MAX_QUEUES 1
+#define TM_THREADX_MAX_SEMAPHORES 1
+#define TM_THREADX_MAX_MEMORY_POOLS 1
+
+
+/* Define the default ThreadX stack size. */
+
+#define TM_THREADX_THREAD_STACK_SIZE 2096
+
+
+/* Define the default ThreadX queue size. */
+
+#define TM_THREADX_QUEUE_SIZE 200
+
+
+/* Define the default ThreadX memory pool size. */
+
+#define TM_THREADX_MEMORY_POOL_SIZE 2048
+
+
+/* Define the number of timer interrupt ticks per second. */
+
+#define TM_THREADX_TICKS_PER_SECOND 100
+
+
+/* Define ThreadX data structures. */
+
+TX_THREAD tm_thread_array[TM_THREADX_MAX_THREADS];
+TX_QUEUE tm_queue_array[TM_THREADX_MAX_QUEUES];
+TX_SEMAPHORE tm_semaphore_array[TM_THREADX_MAX_SEMAPHORES];
+TX_BLOCK_POOL tm_block_pool_array[TM_THREADX_MAX_MEMORY_POOLS];
+
+
+/* Define ThreadX object data areas. */
+
+unsigned char tm_thread_stack_area[TM_THREADX_MAX_THREADS*TM_THREADX_THREAD_STACK_SIZE];
+unsigned char tm_queue_memory_area[TM_THREADX_MAX_QUEUES*TM_THREADX_QUEUE_SIZE];
+unsigned char tm_pool_memory_area[TM_THREADX_MAX_MEMORY_POOLS*TM_THREADX_MEMORY_POOL_SIZE];
+
+
+/* Define array to remember the test entry function. */
+
+void *tm_thread_entry_functions[TM_THREADX_MAX_THREADS];
+
+
+/* Remember the test initialization function. */
+
+void (*tm_initialization_function)(void);
+
+
+/* Define our shell entry function to match ThreadX. */
+
+VOID tm_thread_entry(ULONG thread_input);
+
+
+/* This function called from main performs basic RTOS initialization,
+ calls the test initialization function, and then starts the RTOS function. */
+void tm_initialize(void (*test_initialization_function)(void))
+{
+
+ /* Save the test initialization function. */
+ tm_initialization_function = test_initialization_function;
+
+ /* Call the previously defined initialization function. */
+ (tm_initialization_function)();
+}
+
+
+/* This function takes a thread ID and priority and attempts to create the
+ file in the underlying RTOS. Valid priorities range from 1 through 31,
+ where 1 is the highest priority and 31 is the lowest. If successful,
+ the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_thread_create(int thread_id, int priority, void (*entry_function)(void))
+{
+
+UINT status;
+
+ /* Remember the actual thread entry. */
+ tm_thread_entry_functions[thread_id] = (void *) entry_function;
+
+ /* Create the thread under ThreadX. */
+ status = tx_thread_create(&tm_thread_array[thread_id], "Thread-Metric test", tm_thread_entry, (ULONG) thread_id,
+ &tm_thread_stack_area[thread_id*TM_THREADX_THREAD_STACK_SIZE], TM_THREADX_THREAD_STACK_SIZE,
+ (UINT) priority, (UINT) priority, TX_NO_TIME_SLICE, TX_DONT_START);
+
+ /* Determine if the thread create was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function resumes the specified thread. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_thread_resume(int thread_id)
+{
+
+UINT status;
+
+
+ /* Attempt to resume the thread. */
+ status = tx_thread_resume(&tm_thread_array[thread_id]);
+
+ /* Determine if the thread resume was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function suspends the specified thread. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_thread_suspend(int thread_id)
+{
+
+UINT status;
+
+
+ /* Attempt to suspend the thread. */
+ status = tx_thread_suspend(&tm_thread_array[thread_id]);
+
+ /* Determine if the thread suspend was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function relinquishes to other ready threads at the same
+ priority. */
+void tm_thread_relinquish(void)
+{
+
+ /* Relinquish to other threads at the same priority. */
+ tx_thread_relinquish();
+}
+
+
+/* This function suspends the specified thread for the specified number
+ of seconds. If successful, the function should return TM_SUCCESS.
+ Otherwise, TM_ERROR should be returned. */
+void tm_thread_sleep(int seconds)
+{
+
+ /* Attempt to sleep. */
+ tx_thread_sleep(((UINT) seconds)*TM_THREADX_TICKS_PER_SECOND);
+}
+
+
+/* This function creates the specified queue. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_queue_create(int queue_id)
+{
+
+UINT status;
+
+
+ /* Create the specified queue with 16-byte messages. */
+ status = tx_queue_create(&tm_queue_array[queue_id], "Thread-Metric test", TX_4_ULONG,
+ &tm_queue_memory_area[queue_id*TM_THREADX_QUEUE_SIZE], TM_THREADX_QUEUE_SIZE);
+
+ /* Determine if the queue create was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function sends a 16-byte message to the specified queue. If successful,
+ the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_queue_send(int queue_id, unsigned long *message_ptr)
+{
+
+UINT status;
+
+
+ /* Send the 16-byte message to the specified queue. */
+ status = tx_queue_send(&tm_queue_array[queue_id], message_ptr, TX_NO_WAIT);
+
+ /* Determine if the queue send was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function receives a 16-byte message from the specified queue. If successful,
+ the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_queue_receive(int queue_id, unsigned long *message_ptr)
+{
+
+UINT status;
+
+
+ /* Receive a 16-byte message from the specified queue. */
+ status = tx_queue_receive(&tm_queue_array[queue_id], message_ptr, TX_NO_WAIT);
+
+ /* Determine if the queue receive was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function creates the specified semaphore. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_semaphore_create(int semaphore_id)
+{
+
+UINT status;
+
+
+ /* Create semaphore. */
+ status = tx_semaphore_create(&tm_semaphore_array[semaphore_id], "Thread-Metric test", 1);
+
+ /* Determine if the semaphore create was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function gets the specified semaphore. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_semaphore_get(int semaphore_id)
+{
+
+UINT status;
+
+
+ /* Get the semaphore. */
+ status = tx_semaphore_get(&tm_semaphore_array[semaphore_id], TX_NO_WAIT);
+
+ /* Determine if the semaphore get was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function puts the specified semaphore. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_semaphore_put(int semaphore_id)
+{
+
+UINT status;
+
+
+ /* Put the semaphore. */
+ status = tx_semaphore_put(&tm_semaphore_array[semaphore_id]);
+
+ /* Determine if the semaphore put was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function creates the specified memory pool that can support one or more
+ allocations of 128 bytes. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_memory_pool_create(int pool_id)
+{
+
+UINT status;
+
+
+ /* Create the memory pool. */
+ status = tx_block_pool_create(&tm_block_pool_array[pool_id], "Thread-Metric test", 128, &tm_pool_memory_area[pool_id*TM_THREADX_MEMORY_POOL_SIZE], TM_THREADX_MEMORY_POOL_SIZE);
+
+ /* Determine if the block pool memory was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function allocates a 128 byte block from the specified memory pool.
+ If successful, the function should return TM_SUCCESS. Otherwise, TM_ERROR
+ should be returned. */
+int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr)
+{
+
+UINT status;
+
+
+ /* Allocate a 128-byte block from the specified memory pool. */
+ status = tx_block_allocate(&tm_block_pool_array[pool_id], (void **) memory_ptr, TX_NO_WAIT);
+
+ /* Determine if the block pool allocate was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This function releases a previously allocated 128 byte block from the specified
+ memory pool. If successful, the function should return TM_SUCCESS. Otherwise, TM_ERROR
+ should be returned. */
+int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr)
+{
+
+UINT status;
+
+
+ /* Release the 128-byte block back to the specified memory pool. */
+ status = tx_block_release((void *) memory_ptr);
+
+ /* Determine if the block pool release was successful. */
+ if (status == TX_SUCCESS)
+ return(TM_SUCCESS);
+ else
+ return(TM_ERROR);
+}
+
+
+/* This is the ThreadX thread entry. It is going to call the Thread-Metric
+ entry function saved earlier. */
+VOID tm_thread_entry(ULONG thread_input)
+{
+
+void (*entry_function)(void);
+
+
+ /* Pickup the entry function from the saved array. */
+ entry_function = (void (*)(void)) tm_thread_entry_functions[thread_input];
+
+ /* Call the entry function. */
+ (entry_function)();
+}
+
+
diff --git a/utility/benchmarks/thread_metric/tm_api.h b/utility/benchmarks/thread_metric/tm_api.h
new file mode 100644
index 00000000..b0bf6028
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_api.h
@@ -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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Application Interface (API) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* APPLICATION INTERFACE DEFINITION RELEASE */
+/* */
+/* tm_api.h PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the basic Application Interface (API) */
+/* implementation source code for the Thread-Metrics performance */
+/* test suite. All service prototypes and data structure definitions */
+/* are defined in this file. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+
+#ifndef TM_API_H
+#define TM_API_H
+
+#include "tm_porting_layer.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
+
+/* Define API constants. */
+
+#define TM_SUCCESS 0
+#define TM_ERROR 1
+
+
+/* Define the time interval in seconds. This can be changed with a -D compiler option. */
+
+#ifndef TM_TEST_DURATION
+#define TM_TEST_DURATION 30
+#endif
+
+
+/* Define RTOS Neutral APIs. RTOS vendors should fill in the guts of the following
+ API. Once this is done the Thread-Metric tests can be successfully run. */
+
+void tm_initialize(void (*test_initialization_function)(void));
+int tm_thread_create(int thread_id, int priority, void (*entry_function)(void));
+int tm_thread_resume(int thread_id);
+int tm_thread_suspend(int thread_id);
+void tm_thread_relinquish(void);
+void tm_thread_sleep(int seconds);
+int tm_queue_create(int queue_id);
+int tm_queue_send(int queue_id, unsigned long *message_ptr);
+int tm_queue_receive(int queue_id, unsigned long *message_ptr);
+int tm_semaphore_create(int semaphore_id);
+int tm_semaphore_get(int semaphore_id);
+int tm_semaphore_put(int semaphore_id);
+int tm_memory_pool_create(int pool_id);
+int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr);
+int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr);
+
+
+/* Determine if a C++ compiler is being used. If so, complete the standard
+ C conditional started above. */
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/utility/benchmarks/thread_metric/tm_basic_processing_test.c b/utility/benchmarks/thread_metric/tm_basic_processing_test.c
new file mode 100644
index 00000000..0866ddd6
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_basic_processing_test.c
@@ -0,0 +1,176 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Basic Processing Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_basic_processing_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the basic test for determining board processing */
+/* capabilities */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_basic_processing_counter;
+
+
+/* Test array. We will just do a series of calculations on the
+ test array to eat up processing bandwidth. The idea is that
+ all RTOSes should produce the same metric here if everything
+ else is equal, e.g. processor speed, memory speed, etc. */
+
+volatile unsigned long tm_basic_processing_array[1024];
+
+
+/* Define the test thread prototypes. */
+
+void tm_basic_processing_thread_0_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_basic_processing_thread_report(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_basic_processing_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_basic_processing_initialize);
+}
+
+
+/* Define the basic processing test initialization. */
+
+void tm_basic_processing_initialize(void)
+{
+ /* Create thread 0 at priority 10. */
+ tm_thread_create(0, 10, tm_basic_processing_thread_0_entry);
+
+ /* Resume thread 0. */
+ tm_thread_resume(0);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_basic_processing_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the basic processing thread. */
+void tm_basic_processing_thread_0_entry(void)
+{
+
+int i;
+
+ /* Initialize the test array. */
+ for (i = 0; i < 1024; i++)
+ {
+
+ /* Clear the basic processing array. */
+ tm_basic_processing_array[i] = 0;
+ }
+
+ while(1)
+ {
+
+ /* Loop through the basic processing array, add the previous
+ contents with the contents of the tm_basic_processing_counter
+ and xor the result with the previous value... just to eat
+ up some time. */
+ for (i = 0; i < 1024; i++)
+ {
+
+ /* Update each array entry. */
+ tm_basic_processing_array[i] = (tm_basic_processing_array[i] + tm_basic_processing_counter) ^ tm_basic_processing_array[i];
+ }
+
+ /* Increment the basic processing counter. */
+ tm_basic_processing_counter++;
+ }
+}
+
+
+/* Define the basic processing reporting thread. */
+void tm_basic_processing_thread_report(void)
+{
+
+unsigned long last_counter;
+unsigned long relative_time;
+
+
+ /* Initialize the last counter. */
+ last_counter = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Basic Single Thread Processing Test **** Relative Time: %lu\n", relative_time);
+
+ /* See if there are any errors. */
+ if (tm_basic_processing_counter == last_counter)
+ {
+
+ printf("ERROR: Invalid counter value(s). Basic processing thread died!\n");
+ }
+
+ /* Show the time period total. */
+ printf("Time Period Total: %lu\n\n", tm_basic_processing_counter - last_counter);
+
+ /* Save the last counter. */
+ last_counter = tm_basic_processing_counter;
+ }
+}
diff --git a/utility/benchmarks/thread_metric/tm_cooperative_scheduling_test.c b/utility/benchmarks/thread_metric/tm_cooperative_scheduling_test.c
new file mode 100644
index 00000000..60f94e95
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_cooperative_scheduling_test.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Cooperative Scheduling Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_cooperative_scheduling_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the cooperative scheduling test. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_cooperative_thread_0_counter;
+unsigned long tm_cooperative_thread_1_counter;
+unsigned long tm_cooperative_thread_2_counter;
+unsigned long tm_cooperative_thread_3_counter;
+unsigned long tm_cooperative_thread_4_counter;
+
+
+/* Define the test thread prototypes. */
+
+void tm_cooperative_thread_0_entry(void);
+void tm_cooperative_thread_1_entry(void);
+void tm_cooperative_thread_2_entry(void);
+void tm_cooperative_thread_3_entry(void);
+void tm_cooperative_thread_4_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_cooperative_thread_report(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_cooperative_scheduling_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_cooperative_scheduling_initialize);
+}
+
+
+/* Define the cooperative scheduling test initialization. */
+
+void tm_cooperative_scheduling_initialize(void)
+{
+
+ /* Create all 5 threads at priority 3. */
+ tm_thread_create(0, 3, tm_cooperative_thread_0_entry);
+ tm_thread_create(1, 3, tm_cooperative_thread_1_entry);
+ tm_thread_create(2, 3, tm_cooperative_thread_2_entry);
+ tm_thread_create(3, 3, tm_cooperative_thread_3_entry);
+ tm_thread_create(4, 3, tm_cooperative_thread_4_entry);
+
+ /* Resume all 5 threads. */
+ tm_thread_resume(0);
+ tm_thread_resume(1);
+ tm_thread_resume(2);
+ tm_thread_resume(3);
+ tm_thread_resume(4);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_cooperative_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the first cooperative thread. */
+void tm_cooperative_thread_0_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Relinquish to all other threads at same priority. */
+ tm_thread_relinquish();
+
+ /* Increment this thread's counter. */
+ tm_cooperative_thread_0_counter++;
+ }
+}
+
+/* Define the second cooperative thread. */
+void tm_cooperative_thread_1_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Relinquish to all other threads at same priority. */
+ tm_thread_relinquish();
+
+ /* Increment this thread's counter. */
+ tm_cooperative_thread_1_counter++;
+ }
+}
+
+/* Define the third cooperative thread. */
+void tm_cooperative_thread_2_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Relinquish to all other threads at same priority. */
+ tm_thread_relinquish();
+
+ /* Increment this thread's counter. */
+ tm_cooperative_thread_2_counter++;
+ }
+}
+
+
+/* Define the fourth cooperative thread. */
+void tm_cooperative_thread_3_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Relinquish to all other threads at same priority. */
+ tm_thread_relinquish();
+
+ /* Increment this thread's counter. */
+ tm_cooperative_thread_3_counter++;
+ }
+}
+
+
+/* Define the fifth cooperative thread. */
+void tm_cooperative_thread_4_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Relinquish to all other threads at same priority. */
+ tm_thread_relinquish();
+
+ /* Increment this thread's counter. */
+ tm_cooperative_thread_4_counter++;
+ }
+}
+
+
+/* Define the cooperative test reporting thread. */
+void tm_cooperative_thread_report(void)
+{
+
+unsigned long total;
+unsigned long relative_time;
+unsigned long last_total;
+unsigned long average;
+
+ /* Initialize the last total. */
+ last_total = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Cooperative Scheduling Test **** Relative Time: %lu\n", relative_time);
+
+ /* Calculate the total of all the counters. */
+ total = tm_cooperative_thread_0_counter + tm_cooperative_thread_1_counter + tm_cooperative_thread_2_counter
+ + tm_cooperative_thread_3_counter + tm_cooperative_thread_4_counter;
+
+ /* Calculate the average of all the counters. */
+ average = total/5;
+
+ /* WCC - integrity check */
+ printf("tm_cooperative_thread_0_counter: %d\n", tm_cooperative_thread_0_counter);
+ printf("tm_cooperative_thread_1_counter: %d\n", tm_cooperative_thread_1_counter);
+ printf("tm_cooperative_thread_2_counter: %d\n", tm_cooperative_thread_2_counter);
+ printf("tm_cooperative_thread_3_counter: %d\n", tm_cooperative_thread_3_counter);
+ printf("tm_cooperative_thread_4_counter: %d\n", tm_cooperative_thread_4_counter);
+
+ /* See if there are any errors. */
+ if ((tm_cooperative_thread_0_counter < (average - 1)) ||
+ (tm_cooperative_thread_0_counter > (average + 1)) ||
+ (tm_cooperative_thread_1_counter < (average - 1)) ||
+ (tm_cooperative_thread_1_counter > (average + 1)) ||
+ (tm_cooperative_thread_2_counter < (average - 1)) ||
+ (tm_cooperative_thread_2_counter > (average + 1)) ||
+ (tm_cooperative_thread_3_counter < (average - 1)) ||
+ (tm_cooperative_thread_3_counter > (average + 1)) ||
+ (tm_cooperative_thread_4_counter < (average - 1)) ||
+ (tm_cooperative_thread_4_counter > (average + 1)))
+ {
+
+ printf("ERROR: Invalid counter value(s). Cooperative counters should not be more that 1 different than the average!\n");
+ }
+
+ /* Show the time period total. */
+ printf("Time Period Total: %lu\n\n", total - last_total);
+
+ /* Save the last total. */
+ last_total = total;
+ }
+}
diff --git a/utility/benchmarks/thread_metric/tm_interrupt_preemption_processing_test.c b/utility/benchmarks/thread_metric/tm_interrupt_preemption_processing_test.c
new file mode 100644
index 00000000..04af1f5b
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_interrupt_preemption_processing_test.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Interrupt Preemption Processing Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_interrupt_preemption_processing_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the preemptive scheduling test. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_interrupt_preemption_thread_0_counter;
+unsigned long tm_interrupt_preemption_thread_1_counter;
+unsigned long tm_interrupt_preemption_handler_counter;
+
+
+/* Define the test thread prototypes. */
+
+void tm_interrupt_preemption_thread_0_entry(void);
+void tm_interrupt_preemption_thread_1_entry(void);
+void tm_interrupt_preemption_handler_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_interrupt_preemption_thread_report(void);
+
+
+/* Define the interrupt handler. This must be called from the RTOS. */
+
+void tm_interrupt_preemption_handler(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_interrupt_preemption_processing_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_interrupt_preemption_processing_initialize);
+}
+
+
+/* Define the interrupt processing test initialization. */
+
+void tm_interrupt_preemption_processing_initialize(void)
+{
+
+ /* Create interrupt thread at priority 3. */
+ tm_thread_create(0, 3, tm_interrupt_preemption_thread_0_entry);
+
+ /* Create thread that generates the interrupt at priority 10. */
+ tm_thread_create(1, 10, tm_interrupt_preemption_thread_1_entry);
+
+ /* Resume just thread 1. */
+ tm_thread_resume(1);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_interrupt_preemption_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the interrupt thread. This thread is resumed from the
+ interrupt handler. It runs and suspends. */
+void tm_interrupt_preemption_thread_0_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Increment this thread's counter. */
+ tm_interrupt_preemption_thread_0_counter++;
+
+ /* Suspend. This will allow the thread generating the
+ interrupt to run again. */
+ tm_thread_suspend(0);
+ }
+}
+
+/* Define the thread that generates the interrupt. */
+void tm_interrupt_preemption_thread_1_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Force an interrupt. The underlying RTOS must see that the
+ the interrupt handler is called from the appropriate software
+ interrupt or trap. */
+ TM_CAUSE_INTERRUPT
+
+ /* We won't get back here until the interrupt processing is complete,
+ including the execution of the higher priority thread made ready
+ by the interrupt. */
+
+ /* Increment this thread's counter. */
+ tm_interrupt_preemption_thread_1_counter++;
+ }
+}
+
+
+/* Define the interrupt handler. This must be called from the RTOS trap handler.
+ To be fair, it must behave just like a processor interrupt, i.e. it must save
+ the full context of the interrupted thread during the preemption processing. */
+void tm_interrupt_preemption_handler(void)
+{
+
+ /* Increment the interrupt count. */
+ tm_interrupt_preemption_handler_counter++;
+
+ /* Resume the higher priority thread from the ISR. */
+ tm_thread_resume(0);
+}
+
+
+/* Define the interrupt test reporting thread. */
+void tm_interrupt_preemption_thread_report(void)
+{
+
+unsigned long total;
+unsigned long relative_time;
+unsigned long last_total;
+unsigned long average;
+
+
+ /* Initialize the last total. */
+ last_total = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Interrupt Preemption Processing Test **** Relative Time: %lu\n", relative_time);
+
+ /* Calculate the total of all the counters. */
+ total = tm_interrupt_preemption_thread_0_counter + tm_interrupt_preemption_thread_1_counter + tm_interrupt_preemption_handler_counter;
+
+ /* Calculate the average of all the counters. */
+ average = total/3;
+
+ /* See if there are any errors. */
+ if ((tm_interrupt_preemption_thread_0_counter < (average - 1)) ||
+ (tm_interrupt_preemption_thread_0_counter > (average + 1)) ||
+ (tm_interrupt_preemption_thread_1_counter < (average - 1)) ||
+ (tm_interrupt_preemption_thread_1_counter > (average + 1)) ||
+ (tm_interrupt_preemption_handler_counter < (average - 1)) ||
+ (tm_interrupt_preemption_handler_counter > (average + 1)))
+ {
+
+ printf("ERROR: Invalid counter value(s). Interrupt processing test has failed!\n");
+ }
+
+ /* Show the total interrupts for the time period. */
+ printf("Time Period Total: %lu\n\n", tm_interrupt_preemption_handler_counter - last_total);
+
+ /* Save the last total number of interrupts. */
+ last_total = tm_interrupt_preemption_handler_counter;
+ }
+}
diff --git a/utility/benchmarks/thread_metric/tm_interrupt_processing_test.c b/utility/benchmarks/thread_metric/tm_interrupt_processing_test.c
new file mode 100644
index 00000000..7ed90f8f
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_interrupt_processing_test.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Interrupt Processing Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_interrupt_processing_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the No-preemption interrupt processing test. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_interrupt_thread_0_counter;
+unsigned long tm_interrupt_handler_counter;
+
+
+/* Define the test thread prototypes. */
+
+void tm_interrupt_thread_0_entry(void);
+void tm_interrupt_handler_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_interrupt_thread_report(void);
+
+
+/* Define the interrupt handler. This must be called from the RTOS. */
+
+void tm_interrupt_handler(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_interrupt_processing_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_interrupt_processing_initialize);
+}
+
+
+/* Define the interrupt processing test initialization. */
+
+void tm_interrupt_processing_initialize(void)
+{
+
+ /* Create thread that generates the interrupt at priority 10. */
+ tm_thread_create(0, 10, tm_interrupt_thread_0_entry);
+
+ /* Create a semaphore that will be posted from the interrupt
+ handler. */
+ tm_semaphore_create(0);
+
+ /* Resume just thread 0. */
+ tm_thread_resume(0);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_interrupt_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the thread that generates the interrupt. */
+void tm_interrupt_thread_0_entry(void)
+{
+
+int status;
+
+
+ /* Pickup the semaphore since it is initialized to 1 by default. */
+ status = tm_semaphore_get(0);
+
+ /* Check for good status. */
+ if (status != TM_SUCCESS)
+ return;
+
+ while(1)
+ {
+
+ /* Force an interrupt. The underlying RTOS must see that the
+ the interrupt handler is called from the appropriate software
+ interrupt or trap. */
+ TM_CAUSE_INTERRUPT
+
+ /* We won't get back here until the interrupt processing is complete,
+ including the setting of the semaphore from the interrupt
+ handler. */
+
+ /* Pickup the semaphore set by the interrupt handler. */
+ status = tm_semaphore_get(0);
+
+ /* Check for good status. */
+ if (status != TM_SUCCESS)
+ return;
+
+ /* Increment this thread's counter. */
+ tm_interrupt_thread_0_counter++;
+ }
+}
+
+
+/* Define the interrupt handler. This must be called from the RTOS trap handler.
+ To be fair, it must behave just like a processor interrupt, i.e. it must save
+ the full context of the interrupted thread during the preemption processing. */
+void tm_interrupt_handler(void)
+{
+
+ /* Increment the interrupt count. */
+ tm_interrupt_handler_counter++;
+
+ /* Put the semaphore from the interrupt handler. */
+ tm_semaphore_put(0);
+}
+
+
+/* Define the interrupt test reporting thread. */
+void tm_interrupt_thread_report(void)
+{
+
+unsigned long total;
+unsigned long last_total;
+unsigned long relative_time;
+unsigned long average;
+
+
+ /* Initialize the last total. */
+ last_total = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Interrupt Processing Test **** Relative Time: %lu\n", relative_time);
+
+ /* Calculate the total of all the counters. */
+ total = tm_interrupt_thread_0_counter + tm_interrupt_handler_counter;
+
+ /* Calculate the average of all the counters. */
+ average = total/2;
+
+ /* See if there are any errors. */
+ if ((tm_interrupt_thread_0_counter < (average - 1)) ||
+ (tm_interrupt_thread_0_counter > (average + 1)) ||
+ (tm_interrupt_handler_counter < (average - 1)) ||
+ (tm_interrupt_handler_counter > (average + 1)))
+ {
+
+ printf("ERROR: Invalid counter value(s). Interrupt processing test has failed!\n");
+ }
+
+ /* Show the total interrupts for the time period. */
+ printf("Time Period Total: %lu\n\n", tm_interrupt_handler_counter - last_total);
+
+ /* Save the last total number of interrupts. */
+ last_total = tm_interrupt_handler_counter;
+ }
+}
diff --git a/utility/benchmarks/thread_metric/tm_memory_allocation_test.c b/utility/benchmarks/thread_metric/tm_memory_allocation_test.c
new file mode 100644
index 00000000..cbde4756
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_memory_allocation_test.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Memory Allocation Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_memory_allocation_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the Message exchange processing test. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_memory_allocation_counter;
+
+
+/* Define the test thread prototypes. */
+
+void tm_memory_allocation_thread_0_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_memory_allocation_thread_report(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_memory_allocation_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_memory_allocation_initialize);
+}
+
+
+/* Define the memory allocation processing test initialization. */
+
+void tm_memory_allocation_initialize(void)
+{
+
+ /* Create thread 0 at priority 10. */
+ tm_thread_create(0, 10, tm_memory_allocation_thread_0_entry);
+
+ /* Resume thread 0. */
+ tm_thread_resume(0);
+
+ /* Create a memory pool. */
+ tm_memory_pool_create(0);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_memory_allocation_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the memory allocation processing thread. */
+void tm_memory_allocation_thread_0_entry(void)
+{
+
+int status;
+unsigned char *memory_ptr;
+
+
+ while(1)
+ {
+
+ /* Allocate memory from pool. */
+ tm_memory_pool_allocate(0, &memory_ptr);
+
+ /* Release the memory back to the pool. */
+ status = tm_memory_pool_deallocate(0, memory_ptr);
+
+ /* Check for invalid memory allocation/deallocation. */
+ if (status != TM_SUCCESS)
+ break;
+
+ /* Increment the number of memory allocations sent and received. */
+ tm_memory_allocation_counter++;
+ }
+}
+
+
+/* Define the memory allocation test reporting thread. */
+void tm_memory_allocation_thread_report(void)
+{
+
+unsigned long last_counter;
+unsigned long relative_time;
+
+
+ /* Initialize the last counter. */
+ last_counter = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Memory Allocation Test **** Relative Time: %lu\n", relative_time);
+
+ /* See if there are any errors. */
+ if (tm_memory_allocation_counter == last_counter)
+ {
+
+ printf("ERROR: Invalid counter value(s). Error allocating/deallocating memory!\n");
+ }
+
+ /* Show the time period total. */
+ printf("Time Period Total: %lu\n\n", tm_memory_allocation_counter - last_counter);
+
+ /* Save the last counter. */
+ last_counter = tm_memory_allocation_counter;
+ }
+}
+
diff --git a/utility/benchmarks/thread_metric/tm_message_processing_test.c b/utility/benchmarks/thread_metric/tm_message_processing_test.c
new file mode 100644
index 00000000..35ab53e8
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_message_processing_test.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Message Processing Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/* */
+/* FUCTION RELEASE */
+/* */
+/* tm_message_processing_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* Basic test for message exchange processing. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_message_processing_counter;
+unsigned long tm_message_sent[4];
+unsigned long tm_message_received[4];
+
+
+/* Define the test thread prototypes. */
+
+void tm_message_processing_thread_0_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_message_processing_thread_report(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_message_processing_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_message_processing_initialize);
+}
+
+
+/* Define the message processing test initialization. */
+
+void tm_message_processing_initialize(void)
+{
+
+ /* Create thread 0 at priority 10. */
+ tm_thread_create(0, 10, tm_message_processing_thread_0_entry);
+
+ /* Resume thread 0. */
+ tm_thread_resume(0);
+
+ /* Create a queue for the message passing. */
+ tm_queue_create(0);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_message_processing_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the message processing thread. */
+void tm_message_processing_thread_0_entry(void)
+{
+
+ /* Initialize the source message. */
+ tm_message_sent[0] = 0x11112222;
+ tm_message_sent[1] = 0x33334444;
+ tm_message_sent[2] = 0x55556666;
+ tm_message_sent[3] = 0x77778888;
+
+ while(1)
+ {
+ /* Send a message to the queue. */
+ tm_queue_send(0, tm_message_sent);
+
+ /* Receive a message from the queue. */
+ tm_queue_receive(0, tm_message_received);
+
+ /* Check for invalid message. */
+ if (tm_message_received[3] != tm_message_sent[3])
+ break;
+
+ /* Increment the last word of the 16-byte message. */
+ tm_message_sent[3]++;
+
+ /* Increment the number of messages sent and received. */
+ tm_message_processing_counter++;
+ }
+}
+
+
+/* Define the message test reporting thread. */
+void tm_message_processing_thread_report(void)
+{
+
+unsigned long last_counter;
+unsigned long relative_time;
+
+
+ /* Initialize the last counter. */
+ last_counter = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Message Processing Test **** Relative Time: %lu\n", relative_time);
+
+ /* See if there are any errors. */
+ if (tm_message_processing_counter == last_counter)
+ {
+
+ printf("ERROR: Invalid counter value(s). Error sending/receiving messages!\n");
+ }
+
+ /* Show the time period total. */
+ printf("Time Period Total: %lu\n\n", tm_message_processing_counter - last_counter);
+
+ /* Save the last counter. */
+ last_counter = tm_message_processing_counter;
+ }
+}
diff --git a/utility/benchmarks/thread_metric/tm_porting_layer.h b/utility/benchmarks/thread_metric/tm_porting_layer.h
new file mode 100644
index 00000000..5049eb3f
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_porting_layer.h
@@ -0,0 +1,48 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+#ifndef TM_PORTING_LAYER_H
+#define TM_PORTING_LAYER_H
+
+#include <stdio.h>
+
+
+/* Define the TRAP instruction. This is used by the Interrupt Processing and Interrupt Preemption Processing tests.
+ The SVC instruction below is for Cortex-M architectures using IAR tools. This will likely need to be modified
+ for different processors and/or development tools.
+
+ Note also that for the Interrupt Processing test there is the assumption that the SVC ISR looks like:
+
+ PUBLIC SVC_Handler
+SVC_Handler:
+ PUSH {lr}
+ BL tm_interrupt_handler
+ POP {lr}
+ BX LR
+
+ And that for the Interrupt Preemption Processing test the SVC ISR looks like:
+
+ PUBLIC SVC_Handler
+SVC_Handler:
+ PUSH {lr}
+ BL tm_interrupt_preemption_handler
+ POP {lr}
+ BX LR
+
+ Again, this is very processor/tool specific so changes are likely needed for non Cortex-M/IAR
+ environments. */
+
+#define TM_CAUSE_INTERRUPT asm("SVC #0");
+
+
+
+#endif
+
diff --git a/utility/benchmarks/thread_metric/tm_porting_layer_template.c b/utility/benchmarks/thread_metric/tm_porting_layer_template.c
new file mode 100644
index 00000000..e1190ee0
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_porting_layer_template.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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Porting Layer (Must be completed with RTOS specifics) */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/* Include necessary files. */
+
+#include "tm_api.h"
+
+
+/* This function called from main performs basic RTOS initialization,
+ calls the test initialization function, and then starts the RTOS function. */
+void tm_initialize(void (*test_initialization_function)(void))
+{
+
+}
+
+
+/* This function takes a thread ID and priority and attempts to create the
+ file in the underlying RTOS. Valid priorities range from 1 through 31,
+ where 1 is the highest priority and 31 is the lowest. If successful,
+ the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_thread_create(int thread_id, int priority, void (*entry_function)(void))
+{
+
+}
+
+
+/* This function resumes the specified thread. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_thread_resume(int thread_id)
+{
+
+}
+
+
+/* This function suspends the specified thread. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_thread_suspend(int thread_id)
+{
+
+}
+
+
+/* This function relinquishes to other ready threads at the same
+ priority. */
+void tm_thread_relinquish(void)
+{
+
+}
+
+
+/* This function suspends the specified thread for the specified number
+ of seconds. If successful, the function should return TM_SUCCESS.
+ Otherwise, TM_ERROR should be returned. */
+void tm_thread_sleep(int seconds)
+{
+
+}
+
+
+/* This function creates the specified queue. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_queue_create(int queue_id)
+{
+
+}
+
+
+/* This function sends a 16-byte message to the specified queue. If successful,
+ the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_queue_send(int queue_id, unsigned long *message_ptr)
+{
+
+}
+
+
+/* This function receives a 16-byte message from the specified queue. If successful,
+ the function should return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_queue_receive(int queue_id, unsigned long *message_ptr)
+{
+
+}
+
+
+/* This function creates the specified semaphore. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_semaphore_create(int semaphore_id)
+{
+
+}
+
+
+/* This function gets the specified semaphore. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_semaphore_get(int semaphore_id)
+{
+
+}
+
+
+/* This function puts the specified semaphore. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_semaphore_put(int semaphore_id)
+{
+
+}
+
+
+/* This function creates the specified memory pool that can support one or more
+ allocations of 128 bytes. If successful, the function should
+ return TM_SUCCESS. Otherwise, TM_ERROR should be returned. */
+int tm_memory_pool_create(int pool_id)
+{
+
+}
+
+
+/* This function allocates a 128 byte block from the specified memory pool.
+ If successful, the function should return TM_SUCCESS. Otherwise, TM_ERROR
+ should be returned. */
+int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr)
+{
+
+}
+
+
+/* This function releases a previously allocated 128 byte block from the specified
+ memory pool. If successful, the function should return TM_SUCCESS. Otherwise, TM_ERROR
+ should be returned. */
+int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr)
+{
+
+}
+
+
diff --git a/utility/benchmarks/thread_metric/tm_preemptive_scheduling_test.c b/utility/benchmarks/thread_metric/tm_preemptive_scheduling_test.c
new file mode 100644
index 00000000..c9c02af7
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_preemptive_scheduling_test.c
@@ -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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Preemptive Scheduling Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_preemptive_scheduling_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the preemptive scheduling test. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_preemptive_thread_0_counter;
+unsigned long tm_preemptive_thread_1_counter;
+unsigned long tm_preemptive_thread_2_counter;
+unsigned long tm_preemptive_thread_3_counter;
+unsigned long tm_preemptive_thread_4_counter;
+
+
+/* Define the test thread prototypes. */
+
+void tm_preemptive_thread_0_entry(void);
+void tm_preemptive_thread_1_entry(void);
+void tm_preemptive_thread_2_entry(void);
+void tm_preemptive_thread_3_entry(void);
+void tm_preemptive_thread_4_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_preemptive_thread_report(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_preemptive_scheduling_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_preemptive_scheduling_initialize);
+}
+
+
+/* Define the preemptive scheduling test initialization. */
+
+void tm_preemptive_scheduling_initialize(void)
+{
+
+ /* Create thread 0 at priority 10. */
+ tm_thread_create(0, 10, tm_preemptive_thread_0_entry);
+
+ /* Create thread 1 at priority 9. */
+ tm_thread_create(1, 9, tm_preemptive_thread_1_entry);
+
+ /* Create thread 2 at priority 8. */
+ tm_thread_create(2, 8, tm_preemptive_thread_2_entry);
+
+ /* Create thread 3 at priority 7. */
+ tm_thread_create(3, 7, tm_preemptive_thread_3_entry);
+
+ /* Create thread 4 at priority 6. */
+ tm_thread_create(4, 6, tm_preemptive_thread_4_entry);
+
+ /* Resume just thread 0. */
+ tm_thread_resume(0);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_preemptive_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the first preemptive thread. */
+void tm_preemptive_thread_0_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Resume thread 1. */
+ tm_thread_resume(1);
+
+ /* We won't get back here until threads 1, 2, 3, and 4 all execute and
+ self-suspend. */
+
+ /* Increment this thread's counter. */
+ tm_preemptive_thread_0_counter++;
+ }
+}
+
+/* Define the second preemptive thread. */
+void tm_preemptive_thread_1_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Resume thread 2. */
+ tm_thread_resume(2);
+
+ /* We won't get back here until threads 2, 3, and 4 all execute and
+ self-suspend. */
+
+ /* Increment this thread's counter. */
+ tm_preemptive_thread_1_counter++;
+
+ /* Suspend self! */
+ tm_thread_suspend(1);
+ }
+}
+
+/* Define the third preemptive thread. */
+void tm_preemptive_thread_2_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Resume thread 3. */
+ tm_thread_resume(3);
+
+ /* We won't get back here until threads 3 and 4 execute and
+ self-suspend. */
+
+ /* Increment this thread's counter. */
+ tm_preemptive_thread_2_counter++;
+
+ /* Suspend self! */
+ tm_thread_suspend(2);
+ }
+}
+
+
+/* Define the fourth preemptive thread. */
+void tm_preemptive_thread_3_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Resume thread 4. */
+ tm_thread_resume(4);
+
+ /* We won't get back here until thread 4 executes and
+ self-suspends. */
+
+ /* Increment this thread's counter. */
+ tm_preemptive_thread_3_counter++;
+
+ /* Suspend self! */
+ tm_thread_suspend(3);
+ }
+}
+
+
+/* Define the fifth preemptive thread. */
+void tm_preemptive_thread_4_entry(void)
+{
+
+ while(1)
+ {
+
+ /* Increment this thread's counter. */
+ tm_preemptive_thread_4_counter++;
+
+ /* Self suspend thread 4. */
+ tm_thread_suspend(4);
+ }
+}
+
+
+/* Define the preemptive test reporting thread. */
+void tm_preemptive_thread_report(void)
+{
+
+unsigned long total;
+unsigned long relative_time;
+unsigned long last_total;
+unsigned long average;
+
+
+ /* Initialize the last total. */
+ last_total = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Preemptive Scheduling Test **** Relative Time: %lu\n", relative_time);
+
+ /* Calculate the total of all the counters. */
+ total = tm_preemptive_thread_0_counter + tm_preemptive_thread_1_counter + tm_preemptive_thread_2_counter
+ + tm_preemptive_thread_3_counter + tm_preemptive_thread_4_counter;
+
+ /* Calculate the average of all the counters. */
+ average = total/5;
+
+ /* See if there are any errors. */
+ if ((tm_preemptive_thread_0_counter < (average - 1)) ||
+ (tm_preemptive_thread_0_counter > (average + 1)) ||
+ (tm_preemptive_thread_1_counter < (average - 1)) ||
+ (tm_preemptive_thread_1_counter > (average + 1)) ||
+ (tm_preemptive_thread_2_counter < (average - 1)) ||
+ (tm_preemptive_thread_2_counter > (average + 1)) ||
+ (tm_preemptive_thread_3_counter < (average - 1)) ||
+ (tm_preemptive_thread_3_counter > (average + 1)) ||
+ (tm_preemptive_thread_4_counter < (average - 1)) ||
+ (tm_preemptive_thread_4_counter > (average + 1)))
+ {
+
+ printf("ERROR: Invalid counter value(s). Preemptive counters should not be more that 1 different than the average!\n");
+ }
+
+ /* Show the time period total. */
+ printf("Time Period Total: %lu\n\n", total - last_total);
+
+ /* Save the last total. */
+ last_total = total;
+ }
+}
diff --git a/utility/benchmarks/thread_metric/tm_synchronization_processing_test.c b/utility/benchmarks/thread_metric/tm_synchronization_processing_test.c
new file mode 100644
index 00000000..7f02f0e7
--- /dev/null
+++ b/utility/benchmarks/thread_metric/tm_synchronization_processing_test.c
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/* */
+/* 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. */
+/* */
+/**************************************************************************/
+
+/**************************************************************************/
+/**************************************************************************/
+/** */
+/** Thread-Metric Component */
+/** */
+/** Synchronization Processing Test */
+/** */
+/**************************************************************************/
+/**************************************************************************/
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* tm_synchronization_processing_test PORTABLE C */
+/* 6.1.7 */
+/* AUTHOR */
+/* */
+/* William E. Lamie, Microsoft Corporation */
+/* */
+/* DESCRIPTION */
+/* */
+/* This file defines the Semaphore get/put processing test. */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* 10-15-2021 William E. Lamie Initial Version 6.1.7 */
+/* */
+/**************************************************************************/
+#include "tm_api.h"
+
+
+/* Define the counters used in the demo application... */
+
+unsigned long tm_synchronization_processing_counter;
+
+
+/* Define the test thread prototypes. */
+
+void tm_synchronization_processing_thread_0_entry(void);
+
+
+/* Define the reporting thread prototype. */
+
+void tm_synchronization_processing_thread_report(void);
+
+
+/* Define the initialization prototype. */
+
+void tm_synchronization_processing_initialize(void);
+
+
+/* Define main entry point. */
+
+void tm_main()
+{
+
+ /* Initialize the test. */
+ tm_initialize(tm_synchronization_processing_initialize);
+}
+
+
+/* Define the synchronization processing test initialization. */
+
+void tm_synchronization_processing_initialize(void)
+{
+
+ /* Create thread 0 at priority 10. */
+ tm_thread_create(0, 10, tm_synchronization_processing_thread_0_entry);
+
+ /* Resume thread 0. */
+ tm_thread_resume(0);
+
+ /* Create a semaphore for the test. */
+ tm_semaphore_create(0);
+
+ /* Create the reporting thread. It will preempt the other
+ threads and print out the test results. */
+ tm_thread_create(5, 2, tm_synchronization_processing_thread_report);
+ tm_thread_resume(5);
+}
+
+
+/* Define the synchronization processing thread. */
+void tm_synchronization_processing_thread_0_entry(void)
+{
+
+int status;
+
+ while(1)
+ {
+
+ /* Get the semaphore. */
+ tm_semaphore_get(0);
+
+ /* Release the semaphore. */
+ status = tm_semaphore_put(0);
+
+ /* Check for semaphore put error. */
+ if (status != TM_SUCCESS)
+ break;
+
+ /* Increment the number of semaphore get/puts. */
+ tm_synchronization_processing_counter++;
+ }
+}
+
+
+/* Define the synchronization test reporting thread. */
+void tm_synchronization_processing_thread_report(void)
+{
+
+unsigned long last_counter;
+unsigned long relative_time;
+
+
+ /* Initialize the last counter. */
+ last_counter = 0;
+
+ /* Initialize the relative time. */
+ relative_time = 0;
+
+ while(1)
+ {
+
+ /* Sleep to allow the test to run. */
+ tm_thread_sleep(TM_TEST_DURATION);
+
+ /* Increment the relative time. */
+ relative_time = relative_time + TM_TEST_DURATION;
+
+ /* Print results to the stdio window. */
+ printf("**** Thread-Metric Synchronization Processing Test **** Relative Time: %lu\n", relative_time);
+
+ /* See if there are any errors. */
+ if (tm_synchronization_processing_counter == last_counter)
+ {
+
+ printf("ERROR: Invalid counter value(s). Error getting/putting semaphore!\n");
+ }
+
+ /* Show the time period total. */
+ printf("Time Period Total: %lu\n\n", tm_synchronization_processing_counter - last_counter);
+
+ /* Save the last counter. */
+ last_counter = tm_synchronization_processing_counter;
+ }
+}
diff --git a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c
index 132e9036..5f7955f5 100644
--- a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c
+++ b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c
@@ -23,6 +23,9 @@
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
+/* 10-15-2021 William E. Lamie Modified comment(s), and */
+/* fixed compiler warnings, */
+/* resulting in version 6.1.7 */
/* */
/**************************************************************************/
@@ -405,7 +408,7 @@ BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,
txfr_free(p_stack);
txfr_free(p_task);
TX_FREERTOS_ASSERT_FAIL();
- return NULL;
+ return (BaseType_t)NULL;
}
prio = txfr_prio_fr_to_tx(uxPriority);
@@ -417,7 +420,7 @@ BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,
txfr_free(p_stack);
txfr_free(p_task);
TX_FREERTOS_ASSERT_FAIL();
- return NULL;
+ return (BaseType_t)NULL;
}
p_task->thread.txfr_thread_ptr = p_task;