mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2025-11-16 04:24:48 +00:00
Release 6.1.9
This commit is contained in:
227
utility/benchmarks/thread_metric/thread_metric_readme.txt
Normal file
227
utility/benchmarks/thread_metric/thread_metric_readme.txt
Normal file
@@ -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.
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)();
|
||||
}
|
||||
|
||||
|
||||
102
utility/benchmarks/thread_metric/tm_api.h
Normal file
102
utility/benchmarks/thread_metric/tm_api.h
Normal file
@@ -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
|
||||
176
utility/benchmarks/thread_metric/tm_basic_processing_test.c
Normal file
176
utility/benchmarks/thread_metric/tm_basic_processing_test.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
208
utility/benchmarks/thread_metric/tm_interrupt_processing_test.c
Normal file
208
utility/benchmarks/thread_metric/tm_interrupt_processing_test.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
164
utility/benchmarks/thread_metric/tm_memory_allocation_test.c
Normal file
164
utility/benchmarks/thread_metric/tm_memory_allocation_test.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
170
utility/benchmarks/thread_metric/tm_message_processing_test.c
Normal file
170
utility/benchmarks/thread_metric/tm_message_processing_test.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
48
utility/benchmarks/thread_metric/tm_porting_layer.h
Normal file
48
utility/benchmarks/thread_metric/tm_porting_layer.h
Normal file
@@ -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
|
||||
|
||||
153
utility/benchmarks/thread_metric/tm_porting_layer_template.c
Normal file
153
utility/benchmarks/thread_metric/tm_porting_layer_template.c
Normal file
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
270
utility/benchmarks/thread_metric/tm_preemptive_scheduling_test.c
Normal file
270
utility/benchmarks/thread_metric/tm_preemptive_scheduling_test.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user