mirror of
https://github.com/azure-rtos/threadx
synced 2025-01-30 08:02:57 +08:00
228 lines
9.1 KiB
Plaintext
228 lines
9.1 KiB
Plaintext
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.
|
|
|
|
|