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.

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 '16 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 '13 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 '13 at 16:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.