diff options
| author | Yuxin Zhou <[email protected]> | 2021-10-14 00:51:26 +0000 |
|---|---|---|
| committer | Yuxin Zhou <[email protected]> | 2021-10-14 00:51:26 +0000 |
| commit | 1af8404c54f9c8d3caa2ac3523c2a5f014aecb1c (patch) | |
| tree | 93e4f4d64ec8c21c01b77f19b8e7326e85227e3d /utility | |
| parent | 215df45d4b59d4ce8606a88f566d1d426e64a84c (diff) | |
Release 6.1.9
Diffstat (limited to 'utility')
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; |
