This article summarizes integration of thread metric benchmark into CMRX RTOS. As CMRX doesn’t support MMU-less execution, tests are always executed with full memory isolation enabled.
Above chart shows comparison of CMRX to other RTOSes in terms of “instructions per cycle”. These data is derived from CMRX test score and summarized in table below. This metric estimates instruction count needed to perform one test cycle involving all the typical overhead of the running system. In fact, this metric shows CPU cycles consumed to perform one test cycle rather than instructions. Yet the term “IPC” is used for this purpose and understood in the industry, so we will stick to this use as well.
| Test Name | CMRX RTOS 0.1.2 |
|---|---|
| Calibration | 9.08 |
| Message Passing | 1628.96 |
| Synchronization | 487.21 |
| Cooperative Scheduling | 1035.92 |
| Preemptive Scheduling | 1896.66 |
Purpose: Measures raw processing throughput without kernel overhead.
Method: A single thread continuously increments a counter in a tight loop.
What It Measures: Maximum achievable loop iterations, establishing a baseline for comparing kernel overhead in other tests.
Purpose: Measures voluntary context switch efficiency.
Method: Five threads at equal priority take turns executing. Each thread increments its counter and yields control.
Kernel Functions Used:
sched_yield() - voluntary context switchWhat It Measures: Cost of voluntary context switches when threads explicitly yield CPU to peers of equal priority.
Purpose: Measures priority-based preemptive context switch efficiency.
Method: Five threads with different priorities (6-10) start and stop each other in chain. Thread 0 (lowest priority) sends continuation signal to thread 1, which sends signal to thread 2, cascading up to thread 4 (highest priority). Control then cascades back down. After continuation signal is sent, each thread except of thread 0 stops itself.
Kernel Functions Used:
send_signal() - starting / stopping thread executionWhat It Measures: Cost of involuntary (preemptive) context switches driven by priority differences and thread stopping / starting.
Purpose: Measures message queue operation overhead.
Method: A single thread sends a message to a queue and immediately receives it back, measuring round-trip message passing cost.
Kernel Functions Used:
STATIC_QUEUE_T() - static message queue definitionqueue_send() - send message to queuequeue_receive() - receive message from queueWhat It Measures: Combined cost of enqueueing and dequeueing messages (16-byte messages, queue depth 16).
Purpose: Measures mutex operation overhead.
Method: A single thread repeatedly acquires and releases a mutex, measuring lock/unlock cycle cost.
Kernel Functions Used:
futex_init() - static mutex definitionfutex_lock() - acquire mutexfutex_unlock() - release mutexWhat It Measures: Cost of uncontended mutex acquisition and release (no actual contention since single thread).
Purpose: Measures basic system call overhead
Method: A single thread repeatedly calls get_tid() system call, measuring cost of calling simple system call.
Kernel Functions Used:
get_tid() - simple read-only signal that returns current thread IDWhat It Measures: Cost of simple read-only system call.
Purpose: Measures signal delivery overhead
Method: A single thread repeatedly sends signal to resume to itself. This does nothing besides delivering the signal itself.
Kernel Functions Used:
send_signal() - send signal to threadWhat It Measures: Cost of sending signal to a thread.
Kernel is using default configuration based on standard options:
| Parameter | Value |
|---|---|
| Thread count | 8 |
| Process count | 8 |
| Timers count | 16 |
| Notification buffers | 16 |
| Fast hash function | OFF |