Thread scheduling - unexpected behavior

Discussions and support about ChibiOS/RT, the free embedded RTOS.
Post Reply
Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Thread scheduling - unexpected behavior

Post by Raul »

Hi all,

I have a conceptual/super simple test case whose result I'm struggling to fathom.

All the configuration is as set in the STM32F407 Discovery demo, discovery board is the hardware platform. Tested with -O2 and -O0, no difference.

I wanted to verify that among all the threads ready for execution, the one with the highest priority is the one being executed,
no exceptions to this rule.

It seems to be the case, what I find striking is the behavior of the blinker thread, I would expect it to alternate output state at 10 Hz.

Code: Select all

 22 /*
 23  * This is a periodic thread that does absolutely nothing except flashing
 24  * a LED.
 25  */
 26 static THD_WORKING_AREA(waThread1, 128);
 27 static THD_FUNCTION(Thread1, arg) {
 28
 29   (void)arg;
 30   chRegSetThreadName("blinker");
 31   while (true) {
 32     chThdSleepMilliseconds(100);
 33     palTogglePad(GPIOD, GPIOD_LED3);     /* Orange.  */
 34   }
 35 }
 36
 37 /*
 38  * Application entry point.
 39  */
 40 int main(void) {
 41
 42   /*
 43    * System initializations.
 44    * - HAL initialization, this also initializes the configured device drivers
 45    *   and performs the board-specific initializations.
 46    * - Kernel initialization, the main() function becomes a thread and the
 47    *   RTOS is active.
 48    */
 49   halInit();
 50   chSysInit();
 51
 52   /*
 53    * Creates the example thread.
 54    */
 55   chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+1, Thread1, NULL);
 56
 57   /*
 58    * Normal main() thread activity, in this demo it does toggle
 59    * a yellow led as fast as possible while in running state.
 60    */
 61   while (true)
 62   {
 63         palTogglePad (GPIOD, GPIOD_LED4);       /* Yellow.  */
 64   }
 65 }


Output registered with logic analyzer (colours of the channels map to the leds):

priority.png
priority.png (9.91 KiB) Viewed 9001 times


Any ideas?

Raul
User avatar
wurstnase
Posts: 121
Joined: Tue Oct 17, 2017 2:24 pm
Has thanked: 43 times
Been thanked: 30 times

Re: Thread scheduling - unexpected behavior

Post by wurstnase »

The concept of chibios is a chThdSleep in the main loop.
Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Re: Thread scheduling - unexpected behavior

Post by Raul »

Hi Wurstnase,

That was quick :) Could you elaborate on that please? Is that specific to the main thread? Would the result be any different if I moved the main thread to a separate one, lower priority than blinker and main to sleep infinitely?
From a theoretic perspective, any reason not to have a low priority thread that doesn't sleep?

Raul
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Thread scheduling - unexpected behavior

Post by Giovanni »

Hi,

Main() is a thread at priority NORMALPRIO, if it does not release the CPU then all threads at lower priority will never be scheduled, other threads at NORMALPRIO would be scheduled only if main() calls chThdYield() or its time slice elapsed (depending on if RR scheduling is cooperative or preemptive).

Note that in the test suite there are test cases testing exactly the behaviour you tested, you may look at those too.

Giovanni
Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Re: Thread scheduling - unexpected behavior

Post by Raul »

Hi Giovanni,

Main() is a thread at priority NORMALPRIO, if it does not release the CPU then all threads at lower priority will never be scheduled, other threads at NORMALPRIO would be scheduled only if main() calls chThdYield() or its time slice elapsed (depending on if RR scheduling is cooperative or preemptive).


That makes sense, that was my understanding (for a cooperative kernel like the one in the example). Note that in the example I posted, the blinker thread has a priority of NORMALPRIO+1.

I expanded the example slightly, added a push button to toggle the yellow led in the main.

I thought I had a decent understanding of the scheduler, I would have thought that the orange led would be toggling regularly every 100 ms. Are the results that I am measuring what you would expect?

Code: Select all

 22 /*
 23  * This is a periodic thread that does absolutely nothing except flashing
 24  * a LED.
 25  */
 26 static THD_WORKING_AREA(waThread1, 128);
 27 static THD_FUNCTION(Thread1, arg) {
 28
 29   (void)arg;
 30   chRegSetThreadName("blinker");
 31   while (true) {
 32     chThdSleepMilliseconds(100);
 33     palTogglePad(GPIOD, GPIOD_LED3);     /* Orange.  */
 34   }
 35 }
 36
 37 /*
 38  * Application entry point.
 39  */
 40 int main(void) {
 41
 42   /*
 43    * System initializations.
 44    * - HAL initialization, this also initializes the configured device drivers
 45    *   and performs the board-specific initializations.
 46    * - Kernel initialization, the main() function becomes a thread and the
 47    *   RTOS is active.
 48    */
 49   halInit();
 50   chSysInit();
 51
 52   /*
 53    * Creates the example thread.
 54    */
 55   chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+1, Thread1, NULL);
 56
 57   /*
 58    * Normal main() thread activity, in this demo it does toggle
 59    * a yellow led as fast as possible while in running state.
 60    */
 61   while (true)
 62   {
 63           if (! palReadPad (GPIOA, GPIOA_BUTTON))
 64                 palTogglePad (GPIOD, GPIOD_LED4);       /* Yellow.  */
 65   }
 66 }


Button open
Button open
buttonUnpressed.png (9.55 KiB) Viewed 8987 times

Button closed
Button closed
buttonPressed.png (9.32 KiB) Viewed 8987 times
User avatar
alex31
Posts: 445
Joined: Fri May 25, 2012 10:23 am
Has thanked: 57 times
Been thanked: 88 times

Re: Thread scheduling - unexpected behavior

Post by alex31 »

Hello,

That makes sense, that was my understanding (for a cooperative kernel like the one in the example). Note that in the example I posted, the blinker thread has a priority of NORMALPRIO+1.

I expanded the example slightly, added a push button to toggle the yellow led in the main.

I thought I had a decent understanding of the scheduler, I would have thought that the orange led would be toggling regularly every 100 ms. Are the results that I am measuring what you would expect?


I have reproduced your behavior.

This has nothing to do with the scheduler which work as expected, the problem is on the GPIO side. When you do a toogle, one have to read / modify / write the register, and theses 3 operations are not atomic. So doing this at high frequency without locking on the same port from two threads is the problem.

The problem is solved if :

a/ one keep toogle API but use two pins on two different ports (no shared resource)

or

b/ one replace tooglePad by a setPad followed by clearPad ( theses operations are atomic)

or

c/ one use bitband alias region on MCU that have this capability



Alexandre
Raul
Posts: 43
Joined: Thu Aug 13, 2015 5:15 pm
Has thanked: 3 times
Been thanked: 1 time

Re: Thread scheduling - unexpected behavior

Post by Raul »

Hi Alexandre,

Thanks for taking the time of actually run it and shedding some light, that makes perfect sense (so great to know the cause !). Didn't realiaze about the atomicity of the toggle call.

Also never heard of bit-banding before, appreciated.

Raul
User avatar
wurstnase
Posts: 121
Joined: Tue Oct 17, 2017 2:24 pm
Has thanked: 43 times
Been thanked: 30 times

Re: Thread scheduling - unexpected behavior

Post by wurstnase »

What could be a reason to use a bit-banding instead of the set/reset registers on STM32 (BSRR/BRR)?
User avatar
alex31
Posts: 445
Joined: Fri May 25, 2012 10:23 am
Has thanked: 57 times
Been thanked: 88 times

Re: Thread scheduling - unexpected behavior

Post by alex31 »

What could be a reason to use a bit-banding instead of the set/reset registers on STM32 (BSRR/BRR)?


I don't advocate bitbanding for all the situations. In a set/reset scenario, BSRR/BRR are the way to go (chibios hal use it), it's simpler and faster than using bitbanding. But in the special case of toggling one bit, the hardware take care of atomicity at register level.
User avatar
alex31
Posts: 445
Joined: Fri May 25, 2012 10:23 am
Has thanked: 57 times
Been thanked: 88 times

Re: Thread scheduling - unexpected behavior

Post by alex31 »

Also never heard of bit-banding before, appreciated.


here a small header only library helper for bitbanding :
bitband.h on github

Alexandre
Post Reply