5

I realize sched_rt_period_us and sched_rt_runtime_us are meant to prevent freezing the system in case of runaway RT task. I wonder though, if it's possible to use a small value of sched_rt_period_us to assure the task is running smoothly.

I have a simple job that requires no more than a millisecond or so of CPU time per call - say, driving a stepper motor over GPIO pins. I'd like to achieve no less than 100 cycles per second though, sustained. That's no more than 10% of the CPU time - discounting pre-emption and scheduler overhead.

I've read "very small values in sched_rt_period_us can result in an unstable system"1 but it wasn't said what order of magnitude counts for "a very small value". Can I reliably count on no more than 0.01s delay between calls to my program if I set sched_rt_period_us to 10000 and return control (sched_yield()) in timely manner?

The underlying CPU would likely be 850MHz ARM with a number of other tasks than said control, but none of them realtime or even required to "feel responsive", still, unlike with defaults of sched_rt_period_us and sched_rt_runtime_us (95% out of 1s) I can't allow the RT task to sleep whole 0.05s at a time.

2 Answers 2

3

This is such an old question, let's try. As I understood you are using the anti-deadlock mechanism (this) to avoid starvation of your normal processes because of your RT process.

You say that

I have a simple job that requires no more than a millisecond or so of CPU time per call

Is it a short periodic task or a short task launched by external input?

For the first case (short period tasks): you must know that in Linux kernel 3.14 there became available the SCHED_DEADLINE class. This allows you to set a schedulling policy for your processes so that they'll have at least so much CPU time periodically. Take a look at it's documentation, you'll also find an understandable diagram in the SCHED_DEADLINE section in man 7 sched. If the trigger is external (random, not periodic), then it may not be the solution.

For the second case (short sporadic task): If you can assert that your program will do just a short work each time it's needed, then you can try stop using priorities and just call sched_yield after your job is done. It's a ba approach if busy-pooling. If you really need priorities then maybe you can complement it with usleep, non-rt processes will run while that RT process sleeps. You may also know that if it's triggered by interrupts, then maybe you should use bottom halves, a harder approach.

Mmmm, and something more: you must keep in mind that there can appear more realtime processes than yours. For example, there are kernel threads.

1
  • It's a periodic task, but with changeable period. In two typical applications: driving stepper motor - it's a period (of order of 0.1-0.005s) that is changed by external commands - up to a couple times per second. The second typical application - PWM driver - it's 100 cycles per second, appearing in pairs of calls ("on", "off"), each "on" call exactly 0.02s past the previous "on", but followed by "off" by a variable (externally set) time between 0 and 0.02s - again the delay of "off" changing up to a couple times per second.
    – SF.
    Dec 10, 2016 at 17:26
0

There isn't a whole lot to find related to this question but I did find this thread. It's a bit dated from 2009, and it's regarding the 2.6.X Linux Kernel but seemed apt.

The title of this thread, Subject: question on sched-rt group allocation cap: sched_rt_runtime_us - msg#01766.

excerpt

I have written a small test program that:

(a) forks two threads, one SCHED_FIFO and one SCHED_OTHER (this thread is reniced to -20) and ties both of them to a specific core.

(b) runs both the threads in a tight loop (same number of iterations for both threads) until the SCHED_FIFO thread terminates.

(c) calculates the number of completed iterations of the regular SCHED_OTHER thread against the fixed number of iterations of the SCHED_FIFO thread. It then calculates a percentage based on that.

I am running the above workload against varying sched_rt_runtime_us values (200 ms to 700 ms) keeping the sched_rt_period_us constant at 1000 ms. I have also experimented a little bit by decreasing the value of sched_rt_period_us (thus increasing the sched granularity) with no apparent change in behavior.

My observations are listed in tabular form:

Ratio of # of completed iterations of reg thread / sched_rt_runtime_us / # of iterations of RT thread (in %) sched_rt_runtime_us

  • 0.2 100 % (regular thread completed all its iterations).
  • 0.3 73 %
  • 0.4 45 %
  • 0.5 17 %
  • 0.6 0 % (SCHED_OTHER thread completely throttled. Never ran)
  • 0.7 0 %
2
  • Unfortunately this is for sched_rt_period_us = 1s and heavy workload - system overhead almost insignificant to task work time. My case is pretty much opposite, very short period, light workload, extremely frequent task switching = big system overhead.
    – SF.
    Nov 30, 2013 at 16:15
  • @SF - yeah that's what I was afraid of. This thread was about the only thing I could dig up related to this. I think you might need to do as this author and create a little testing app scenario similar to theirs and sweep the range of values to see what happens.
    – slm
    Nov 30, 2013 at 16:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .