Release 6.1.9

This commit is contained in:
Yuxin Zhou
2021-10-14 00:51:26 +00:00
parent 215df45d4b
commit 1af8404c54
1812 changed files with 60698 additions and 249862 deletions

View 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.

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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)();
}

View 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

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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

View 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)
{
}

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;