argon-rtos
argon-rtos copied to clipboard
Thread<->IRQ synchronization with semaphore breaks timing in tickless mode
Hi, I noticed a problem with thread waking from sleep in tickless mode. When there is thread synced (infinite timeout) by semaphore from ISR, whole system timing breaks. All sleeps in other threads are much shorter.
~~Note: Now I am syncing using simple suspend and resume principle which works.~~ Not, it does not, same problem.
Hi @diggit, sorry for the delay in replying, and thanks for the bug report. Can you provide more information about what you are seeing, I don't totally understand the issue. Specifically, what do you mean by "system timing breaks" and "all sleeps in other threads are much shorter"? Do you have an example? Thanks!
Hi, it's been a while since found this problem. By "system timing breaks" and "all sleeps in other threads are much shorter" I meant, that 100ms sleeps did not take 100ms anymore, but they were shorter (eg simple LED blinking thread looped much faster). Even load monitoring started to return nonsense.
My case was one thread loop of: waiting for semaphore and then drawing on display FB. There was IRQ handler swapping FBs and incrementing semaphore when there was FB ready to be filled (drawn into). This caused LED blinking thread to loop much faster and breaking other timing dependent things.
As far as I understood correctly then this rtos soft real time and decrease or increase the time when running can be normal. It is worth understanding that soft real-time rtos cannot guarantee accurate time intervals. Need more debugging information or code that is tied to the time that would understand what is bug and what is not correctly written.
ok, back to this issue
Lets have one thread blinking with LED:
void blink_thread_fcn(void *arg)
{
while(1)
{
gpio_set(PB13);
Ar::Thread::sleep(10);
gpio_clr(PB13);
Ar::Thread::sleep(40);
}
}
Timing, when there is no other interrupt source.

Now, let's add some other interrupt source. Eg, timer which periodically fires interrupt and wakes thread that flips output.
void irq_trig_blink_thread_fcn(void *args) {
static bool ledOn = false;
while(1) {
if(ledOn) {
gpio_clr(PB14);
}
else {
gpio_set(PB14);
}
ledOn = !ledOn;
Ar::Thread::getCurrent()->suspend();
}
}
extern "C" void TIM7_IRQHandler(void) {
TIM7->SR = ~TIM_SR_UIF;
irq_trig_blink_thread.resume();
}
This part is biased by my WIP patches to #11, skip to next comment, sorry!
Out of nowhere, both sleeps got extended by another kSchedulerQuanta_ms (10ms) and notice those glitches. Like first blinking thread was called and 10ms sleep for on time was completely ignored.

Here with 30Hz interrupt source

When irq_trig_blink_thread.resume(); is called, scheduler is executed afterwards. I am suspecting, that schedulers re-configures systick. Scheduler itself was not called at its' tick period
Here are highlighted time segments. Green (4) are segments 10ms long which corresponds to 4 * kSchedulerQuanta_ms (4 * 10ms) . Red are segments which got interrupted by second timer and scheduler reconfigured and reset systick. Because Argon measures time in ticks of kSchedulerQuanta_ms, shorter sleep times ceil to 0 passed ticks and Argon thinks, that no delay passed yet.

Problem seems to be pretty obvious. We could ignore sleeping threads and not reconfigure systick when the scheduler is not triggered from systick. Could this cause any problems?
With 30Hz second timer interrupt:

Thread priority has no noticeable effect.