|Exploring Edison - Almost Real Time Linux
|Written by Harry Fairhead
|Tuesday, 20 October 2015
Page 2 of 3
Setting Scheduling Priority
This sounds like chaos but if you think about it for a moment and start simply you will see that it provides most of what you are looking for. You are in full control of the Edison and so you can determine exactly how many non-zero priority threads there are. By default all of the standard threads are priority zero and scheduled by the normal scheduler.
Now consider what happens if you start a FIFO scheduled thread with priority 1.
It starts and is added to the end of the priority 1 queue. Of course it is the only priority 1 process and so it starts immediately on one of the two cores available. If the process never makes a call that causes it to wait for I/O say or become blocked in some other way then it will execute without being interrupted by any other process.
In principle this should ensure that your process never delivers anything but its fastest response time.
This is almost but not quite true.
There are more complex situations you can invent with threads at different priorities according to how important they are but this gets complicated very quickly.
A modification to the SCHED_FIFO scheduler is SCHED_RR - for Round Robin. In this case everything works as for SCHED_FIFO except that each running process is only allowed to run for a single time slice. When the time slice is up the thread at the head of the priority queue is started and the current thread is added to the end of the queue. You can see that this allows each thread to run for around one time slice in turn - which is a round robin scheduler.
In most cases for real time programming with the Edison the SCHED_FIFO scheduler is what you need and in its simplest form.
The complete set of scheduling commands are:
The scheduling types supported are:
SCHED_OTHER the standard round-robin time-sharing policy
SCHED_BATCH for "batch" style execution of processes
SCHED_IDLE for running very low priority background jobs
SCHED_FIFO a first-in, first-out policy
SCHED_RR a round-robin policy
where only the final two are real time schedulers.
Also notice that all of the scheduling function return an error code which you should check to make sure thing have worked. For simplicity the examples that follow ignore this advice.
How Bad Is The Problem?
The first question we need to answer is how bad the situation is without real time scheduling.
This is not an easy question to answer because it depends on so many factors. Take, for example, a very simple program which toggles a GPIO line as fast as it can using mraa:
As we have already discovered we can generate pulses at around 15 microseconds wide using this method.
The real question is how does the scheduler change this pulse length by interrupting your program?
Inspecting about one second's worth of readings with a logic analyser reveals that the pulse length can be as large as 100 microseconds:
A frequency count of pulse sizes is also interesting:
You can see that there were nearly 100 pulses in the 60-70 microsecond range and just two in the 100-200 range.
This might not seem too bad, but if the CPU is loaded just a little then things look much worse.
Add eight CPU-hogging processes and the results are:
The frequency table is also interesting:
Yes, with these conditions there were four instances of greater than 10 millisecond pulses. This means that the program was suspended for 40 milliseconds in a one second sample.
If you try the same thing using fast mraa memory mapping you will find that you get few interruptions on a lightly loaded system as long as you don't make a system call like usleep. However, if the loading is increased the thread is suspended for increasingly large amounts of time.
|Last Updated ( Tuesday, 14 March 2017 )