Skip to content

Commit ada4cde

Browse files
RTX5: fix Round-Robin (#228, #1000)
Round-Robin timeout value is not reset any more when switching to higher priority threads.
1 parent 8fc0679 commit ada4cde

File tree

6 files changed

+43
-46
lines changed

6 files changed

+43
-46
lines changed

CMSIS/DoxyGen/RTOS2/src/cmsis_os2.txt

-8
Original file line numberDiff line numberDiff line change
@@ -290,9 +290,6 @@ a blocking RTOS-call execution is switched back to thread 3 immediately during t
290290
At time index 5 thread 3 uses a blocking RTOS-call as well. Thus the scheduler switches back to thread 2 for time index 6.
291291
At time index 7 the scheduler uses the round-robin mechanism to switch to thread 1 and so on.
292292

293-
\note Refer to limitations this type of scheduling in the \ref systemConfig_rr configuration section.
294-
295-
296293
\section MemoryAllocation Memory Allocation
297294

298295
RTX5 objects (thread, mutex, semaphore, timer, message queue, thread and event flags, as well as memory pool) require
@@ -807,11 +804,6 @@ In other words, threads execute for the duration of their time slice (unless a t
807804
switches to the next thread that is in \b READY state and has the same priority. If no other thread with the same priority is
808805
ready to run, the current running thread resumes it execution.
809806

810-
\note
811-
When switching to higher priority threads, the round-robin timeout value is reset. This might lead to conditions where
812-
threads with the same priority as the interrupted thread are blocked for a longer period of time or even never called
813-
again. You can avoid this by using \ref osThreadYield to pass control to the next thread in the \b READY state.
814-
815807
Round-Robin multitasking is controlled with the <b>\#define OS_ROBIN_ENABLE</b>. The time slice period is configured (in RTX
816808
timer ticks) with the <b>\#define OS_ROBIN_TIMEOUT</b>.
817809

CMSIS/DoxyGen/RTOS2/src/history.txt

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
<td>
104104
- CVE-2021-27431 vulnerability mitigation.
105105
- Added OS Initialization for IAR.
106+
- Fixed Round-Robin (timeout value is not reset when switching to higher priority threads).
106107
- Enhanced stack overrun checking.
107108
- Updated configuration (Event Recorder).
108109
- Reorganized and optimized IRQ modules.

CMSIS/RTOS2/RTX/Include/rtx_os.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ typedef struct osRtxThread_s {
111111
struct osRtxThread_s *delay_next; ///< Link pointer to next Thread in Delay list
112112
struct osRtxThread_s *delay_prev; ///< Link pointer to previous Thread in Delay list
113113
struct osRtxThread_s *thread_join; ///< Thread waiting to Join
114-
uint32_t delay; ///< Delay Time
114+
uint32_t delay; ///< Delay Time/Round Robin Time Tick
115115
int8_t priority; ///< Thread Priority
116116
int8_t priority_base; ///< Base Priority
117117
uint8_t stack_frame; ///< Stack Frame (EXC_RETURN[7..0])
@@ -297,9 +297,9 @@ typedef struct {
297297
osRtxThread_t *delay_list; ///< Delay List
298298
osRtxThread_t *wait_list; ///< Wait List (no Timeout)
299299
osRtxThread_t *terminate_list; ///< Terminate Thread List
300+
uint32_t reserved;
300301
struct { ///< Thread Round Robin Info
301302
osRtxThread_t *thread; ///< Round Robin Thread
302-
uint32_t tick; ///< Round Robin Time Tick
303303
uint32_t timeout; ///< Round Robin Timeout
304304
} robin;
305305
} thread;

CMSIS/RTOS2/RTX/RTX5.scvd

+12-9
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,7 @@
370370
<member name="thread_wait_list" type="*osRtxThread_t" offset="48" info="Wait list (no timeout)"/>
371371
<member name="thread_terminate_list" type="*osRtxThread_t" offset="52" info="Terminate list"/>
372372

373-
<member name="thread_robin_thread" type="*osRtxThread_t" offset="56" info="Round Robin thread"/>
374-
<member name="thread_robin_tick" type="uint32_t" offset="60" info="Round Robin time tick"/>
373+
<member name="thread_robin_thread" type="*osRtxThread_t" offset="60" info="Round Robin thread"/>
375374
<member name="thread_timeout" type="uint32_t" offset="64" info="Round Robin timeout"/>
376375

377376
<member name="timer_list" type="*osRtxTimer_t" offset="68" info="Active timer list"/>
@@ -404,6 +403,8 @@
404403
<member name="mpi_semaphore" type="*osRtxMpInfo_t" offset="152" info="Semaphore control blocks"/>
405404
<member name="mpi_memory_pool" type="*osRtxMpInfo_t" offset="156" info="Memory pool control blocks"/>
406405
<member name="mpi_message_queue" type="*osRtxMpInfo_t" offset="160" info="Message queue control blocks"/>
406+
407+
<var name="robin_tick" type="uint32_t" info="Round Robin time tick (thread_robin_thread.delay)"/>
407408
</typedef>
408409

409410
<!-- OS Runtime Object Memory Usage structure -->
@@ -822,16 +823,18 @@
822823
<readlist cond="(mem_list_com[i].len &amp; 1) &amp;&amp; (mem_list_com[i].id == 0xFA)" name="QCB" type="osRtxMessageQueue_t" offset="addr" count="1" />
823824
</list>
824825

825-
<!-- Read thread wait list -->
826-
<readlist name="TWL" cond="RTX_En &amp;&amp; os_Info.thread_wait_list" type="osRtxThread_t" offset="os_Info.thread_wait_list" next="delay_next"/>
827-
828826
<!-- Validate and process Thread control blocks -->
829827
<list name="i" start="0" limit="TCB._count">
830828
<calc>
831829
TCB[i].cb_valid = (TCB[i].id == 0xF1) &amp;&amp; (TCB[i].state != 0) &amp;&amp; (TCB[i].sp != 0);
832830
TCB[i].sp_valid = 1;
833831
</calc>
834832

833+
<!-- Set Round Robin time tick from the running thread tick value -->
834+
<calc cond="(TCB[i].state == 2) &amp;&amp; os_Config.robin_timeout">
835+
os_Info.robin_tick = TCB[i].delay;
836+
</calc>
837+
835838
<!-- Stack pointer for running thread -->
836839
<calc cond="(TCB[i].state == 2) &amp;&amp; (__Running == 0)">
837840
ipsr = __GetRegVal("XPSR") &amp; 0x01FF;
@@ -1099,10 +1102,10 @@
10991102
<item property="Kernel State" value="%E[os_Info.kernel_state]" cond="RTX_En != 0"/>
11001103
<item property="Kernel Tick Count" value="%d[os_Info.kernel_tick]" cond="RTX_En != 0"/>
11011104
<item property="Kernel Tick Frequency" value="%d[os_Config.tick_freq]" cond="RTX_En != 0" />
1102-
<item property="Round Robin" value="Disabled" cond="(os_Config.robin_timeout == 0) &amp;&amp; (RTX_En != 0)" />
1103-
<item property="Round Robin Tick Count" value="%d[os_Info.thread_robin_tick]" cond="(os_Config.robin_timeout > 0) &amp;&amp; (RTX_En != 0)" />
1104-
<item property="Round Robin Timeout" value="%d[os_Config.robin_timeout]" cond="(os_Config.robin_timeout > 0) &amp;&amp; (RTX_En != 0)" />
1105-
<item property="Global Dynamic Memory" value="Not used" cond="(os_Config.mem_common_size == 0) &amp;&amp; (RTX_En != 0)"/>
1105+
<item property="Round Robin" value="Disabled" cond="(os_Config.robin_timeout == 0) &amp;&amp; (RTX_En != 0)" />
1106+
<item property="Round Robin Tick Count" value="%d[os_Info.robin_tick]" cond="(os_Config.robin_timeout > 0) &amp;&amp; (RTX_En != 0)" />
1107+
<item property="Round Robin Timeout" value="%d[os_Config.robin_timeout]" cond="(os_Config.robin_timeout > 0) &amp;&amp; (RTX_En != 0)" />
1108+
<item property="Global Dynamic Memory" value="Not used" cond="(os_Config.mem_common_size == 0) &amp;&amp; (RTX_En != 0)"/>
11061109
<item property="Global Dynamic Memory" value="Base: %x[mem_head_com._addr], Size: %d[mem_head_com.size], Used: %d[mem_head_com.used], Max used: %d[mem_head_com.max_used]" cond="(os_Config.mem_common_size != 0) &amp;&amp; (RTX_En != 0)"/>
11071110
<item property="Stack Overrun Check" value="%t[os_Config.stack_check ? &quot;Enabled&quot; : &quot;Disabled&quot;]" cond="RTX_En != 0"/>
11081111
<item property="Stack Usage Watermark" value="%t[os_Config.stack_wmark ? &quot;Enabled&quot; : &quot;Disabled&quot;]" cond="RTX_En != 0"/>

CMSIS/RTOS2/RTX/Source/rtx_system.c

+27-25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013-2019 Arm Limited. All rights reserved.
2+
* Copyright (c) 2013-2021 Arm Limited. All rights reserved.
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*
@@ -122,38 +122,40 @@ void osRtxTick_Handler (void) {
122122
OS_Tick_AcknowledgeIRQ();
123123
osRtxInfo.kernel.tick++;
124124

125-
// Process Timers
126-
if (osRtxInfo.timer.tick != NULL) {
127-
osRtxInfo.timer.tick();
128-
}
129-
130125
// Process Thread Delays
131126
osRtxThreadDelayTick();
132127

133128
osRtxThreadDispatch(NULL);
134129

130+
// Process Timers
131+
if (osRtxInfo.timer.tick != NULL) {
132+
osRtxInfo.timer.tick();
133+
}
134+
135135
// Check Round Robin timeout
136136
if (osRtxInfo.thread.robin.timeout != 0U) {
137-
if (osRtxInfo.thread.robin.thread != osRtxInfo.thread.run.next) {
138-
// Reset Round Robin
139-
osRtxInfo.thread.robin.thread = osRtxInfo.thread.run.next;
140-
osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout;
141-
} else {
142-
if (osRtxInfo.thread.robin.tick != 0U) {
143-
osRtxInfo.thread.robin.tick--;
137+
thread = osRtxInfo.thread.run.next;
138+
if (thread != osRtxInfo.thread.robin.thread) {
139+
osRtxInfo.thread.robin.thread = thread;
140+
if (thread->delay == 0U) {
141+
// Reset Round Robin
142+
thread->delay = osRtxInfo.thread.robin.timeout;
144143
}
145-
if (osRtxInfo.thread.robin.tick == 0U) {
146-
// Round Robin Timeout
147-
if (osRtxKernelGetState() == osRtxKernelRunning) {
148-
thread = osRtxInfo.thread.ready.thread_list;
149-
if ((thread != NULL) && (thread->priority == osRtxInfo.thread.robin.thread->priority)) {
150-
osRtxThreadListRemove(thread);
151-
osRtxThreadReadyPut(osRtxInfo.thread.robin.thread);
152-
EvrRtxThreadPreempted(osRtxInfo.thread.robin.thread);
153-
osRtxThreadSwitch(thread);
154-
osRtxInfo.thread.robin.thread = thread;
155-
osRtxInfo.thread.robin.tick = osRtxInfo.thread.robin.timeout;
156-
}
144+
}
145+
if (thread->delay != 0U) {
146+
thread->delay--;
147+
}
148+
if (thread->delay == 0U) {
149+
// Round Robin Timeout
150+
if (osRtxKernelGetState() == osRtxKernelRunning) {
151+
thread = osRtxInfo.thread.ready.thread_list;
152+
if ((thread != NULL) && (thread->priority == osRtxInfo.thread.robin.thread->priority)) {
153+
osRtxThreadListRemove(thread);
154+
osRtxThreadReadyPut(osRtxInfo.thread.robin.thread);
155+
EvrRtxThreadPreempted(osRtxInfo.thread.robin.thread);
156+
osRtxThreadSwitch(thread);
157+
osRtxInfo.thread.robin.thread = thread;
158+
thread->delay = osRtxInfo.thread.robin.timeout;
157159
}
158160
}
159161
}

CMSIS/RTOS2/RTX/Source/rtx_thread.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ static void osRtxThreadDelayRemove (os_thread_t *thread) {
313313
osRtxInfo.thread.delay_list = thread->delay_next;
314314
}
315315
}
316+
thread->delay = 0U;
316317
}
317318

318319
/// Process Thread Delay Tick (executed each System Tick).
@@ -1046,8 +1047,6 @@ static osStatus_t svcRtxThreadSuspend (osThreadId_t thread_id) {
10461047

10471048
// Update Thread State and put it into Delay list
10481049
thread->state = osRtxThreadBlocked;
1049-
thread->thread_prev = NULL;
1050-
thread->thread_next = NULL;
10511050
osRtxThreadDelayInsert(thread, osWaitForever);
10521051
}
10531052

0 commit comments

Comments
 (0)