Thread-Metric measures RTOS primitive throughput by counting operations completed in a fixed time interval (default 30 seconds). Results enable direct comparison across different RTOS implementations on the same hardware.
Originally from Microsoft's ThreadX repository, released under the MIT license.
| Test | File | What it measures |
|---|---|---|
| Basic Processing | src/basic_processing.c |
Single-thread throughput (baseline for scaling results) |
| Cooperative Scheduling | src/cooperative_scheduling.c |
5 equal-priority threads doing round-robin relinquish |
| Preemptive Scheduling | src/preemptive_scheduling.c |
5 threads at different priorities doing resume/suspend chains |
| Interrupt Processing | src/interrupt_processing.c |
Software trap -> ISR posts semaphore -> thread picks it up |
| Interrupt Preemption | src/interrupt_preemption_processing.c |
Software trap -> ISR resumes higher-priority thread |
| Message Processing | src/message_processing.c |
Single thread send/receive of 4-unsigned-long queue messages |
| Synchronization | src/synchronization_processing.c |
Single thread semaphore get/put cycle |
| Memory Allocation | src/memory_allocation.c |
Single thread 128-byte block allocate/deallocate cycle |
configs/
Kconfig # Build configuration schema (RTOS, target, options)
*_defconfig # Pre-made configurations for each RTOS+target
mk/
build.mk # Toolchain, flags, build directory, verbosity
include/
tm_api.h # RTOS-neutral API (14 functions + tm_cause_interrupt)
src/
*.c # One test per file, each defines tm_main()
ports/
common/
cortex-m/ # Shared Cortex-M3 bootstrap for QEMU mps2-an385
startup.S # Reset handler, BSS/data init, semihosting setup
vector_table.c # Default NVIC handlers (weak aliases)
mps2_an385.ld # Linker script (4 MB FLASH + 4 MB SRAM)
threadx/ # ThreadX porting layer
tm_port.c # 14-function API implementation
main.c # Entry point
posix-host/ # POSIX simulator config (Linux/macOS)
cortex-m/ # Cortex-M3 QEMU support (SVC dispatch, SysTick)
freertos/ # FreeRTOS porting layer
tm_port.c # 14-function API implementation
main.c # Entry point
posix-host/ # POSIX simulator config (FreeRTOSConfig.h)
cortex-m/ # Cortex-M3 QEMU support (NVIC IRQ dispatch)
scripts/
qemu-run.sh # QEMU runner with semihosting + timeout
Two layers, one boundary: tests call the API in tm_api.h, the porting layer
maps those calls to real RTOS primitives. Each binary links exactly one test
source file.
| RTOS | POSIX Host | Cortex-M QEMU | Interrupt Tests |
|---|---|---|---|
| ThreadX | yes | yes (mps2-an385) | yes |
| FreeRTOS | yes | yes (mps2-an385) | yes |
Both ports have been tested with all 8 tests on both targets (make check).
Implement the 14 functions declared in tm_api.h plus tm_cause_interrupt().
See ports/threadx/tm_port.c or ports/freertos/tm_port.c for references.
Requirements for fair benchmarking:
- Functions must be real calls, not macros
tm_thread_sleepneeds a 10 ms periodic tick source- Queue messages are
4 * sizeof(unsigned long)bytes (16 on ILP32, 32 on LP64) - Memory pool blocks are 128 bytes
- No cache locking of test or RTOS code regions
- Use 30-second measurement intervals
The build system uses Kconfiglib for RTOS and target selection. Kconfiglib is downloaded automatically on first use.
Configure once, then build:
make defconfig # Apply default config (ThreadX + POSIX host)
make # Build all test binariesOr configure and build in a single command:
make defconfig allNamed defconfig files provide pre-made configurations:
make threadx_posix_defconfig # ThreadX + POSIX host
make threadx_cortex_m_defconfig # ThreadX + Cortex-M3 QEMU
make freertos_posix_defconfig # FreeRTOS + POSIX host
make freertos_cortex_m_defconfig # FreeRTOS + Cortex-M3 QEMUFor interactive configuration with a menu interface:
make configThe RTOS kernel is cloned automatically on first build (ThreadX from eclipse-threadx/threadx, FreeRTOS from FreeRTOS/FreeRTOS-Kernel).
make # Build all test binaries
make tm_basic_processing # Build a single test
make check # Build with 3 s intervals + 1 cycle, run all tests
make clean # Remove binaries and build directory
make distclean # Also remove .config, cloned RTOS trees, Kconfiglib
make help # Show all available targets and overridesThreadX POSIX port uses pthread_setschedparam, which requires elevated
privileges on Linux:
sudo ./tm_basic_processingFreeRTOS POSIX port runs without sudo.
Requires arm-none-eabi-gcc and qemu-system-arm. The build system
auto-sets CROSS_COMPILE=arm-none-eabi- and validates the cross-compiler
exists before building. Override with an explicit path if needed:
make CROSS_COMPILE=/opt/toolchain/arm-none-eabi/bin/arm-none-eabi-Run under QEMU (auto-terminates via semihosting after one report):
make runOr run the QEMU script directly:
scripts/qemu-run.sh tm_basic_processing -semihosting-config enable=on,target=nativeKconfig options can be set via make config (interactive) or by editing
.config directly:
| Option | Default | Effect |
|---|---|---|
CONFIG_TEST_DURATION |
30 | Reporting interval in seconds |
CONFIG_TEST_CYCLES |
0 | Reports before exit (0 = infinite) |
CONFIG_OPTIMIZE_SIZE |
n | Use -Os instead of -O2 |
CONFIG_DEBUG_SYMBOLS |
n | Add -g |
CONFIG_SANITIZERS |
n | Enable ASan/UBSan (POSIX host only) |
Command-line overrides still work for test parameters:
make TM_TEST_DURATION=5 TM_TEST_CYCLES=1Verbose build output:
make V=1- Create
ports/<rtos>/tm_port.cimplementing the 14 functions intm_api.h - Create
ports/<rtos>/main.cwith RTOS-specific startup - For POSIX host: provide configuration headers in
ports/<rtos>/posix-host/ - For Cortex-M QEMU: provide RTOS config and ISR dispatch in
ports/<rtos>/cortex-m/; the shared bootstrap inports/common/cortex-m/handles reset, vector table, and linker script - Add a
CONFIG_RTOS_<NAME>choice entry inconfigs/Kconfig - Add an
ifeq ($(CONFIG_RTOS_<NAME>),y)block in the Makefile - Create
configs/<rtos>_posix_defconfigandconfigs/<rtos>_cortex_m_defconfig