RK0

The Real-Time Kernel '0'

RFC: About Real-Time, Responsiveness and Throughput

I was reading a book provided by a mainstream real-time kernel (which I acknowledge as high-quality). When discussing time-slicing and periodic tasks, the book notes that not using time-slicing would result in decreased fairness for tasks with the same priority, and therefore, it is an ‘advanced technique’. I disagree with the term ‘advanced‘; I would say it is the standard technique for real-time programming.

A real-time system is a system that keeps pace with the real environment it controls. RK0 design choices are aligned with this reasoning. Fairness is hardly a thing.

We want our computations result to be time-bound. The multi-tasking environment must help the programmer to guarantee a maximum (worst-case) response time for a given input.

The RK0 scheduler is designed to provide a straightforward model for reasoning about how tasks are scheduled. Note that this approach does not hinder the application from being written in a manner that contemplates fairness. It is up to the programmer to explicitly orchestrate how to achieve that.

The Importance of Being Idle

If you were to choose when to provide input for the real-time computer, you would do so when this computer is IDLE. At this point, it is totally free to accept your request and then more likely to make the computation result available when it is still useful (or the best QoS).

That is why when designing for real-time, we care about CPU load and tune our system to be in IDLE state for a good amount of time. As the number of tasks increases, this time converges to a minimum ~30%, according to the Rate-Monotonic Assignment model. (There are exceptions, as when tasks run on ‘harmonic’ rates).

The RMA model assumes tasks have deadlines equal to their periods. We do not assign deadlines or periods for our tasks—the priorities are an indirect way of doing so. (PS: a scheduling model that explicitly assigns deadlines to tasks is the Earliest Deadline First (EDF) model – rarely seen on available real-time kernels.)

The complexity of designing for physical processes arises from the fact that these processes are constrained by parameters we cannot control. A given plant might have a time constant that defines the rate at which the equipment heats; it is a physical property that we cannot change. The real-time computer must be able to compute and provide a new input value to the plant to cool it down before damage occurs.

The points

If your system is primarily driven by external events, the environment itself is effectively setting the “clock” or pacing your tasks. In that scenario, each event (interrupt, message, signal) triggers the corresponding task, and we mind about:

  1. Priority Assignment reflects how critical or frequent these events are (so the highest-frequency or shortest-deadline tasks get immediate CPU time).
  2. Execution + Blocking Time is short enough that the task can be ready again before the next event arrives (i.e., it finishes handling one sample or trigger in time for the next).
  3. Throughput: we want to ensure that your tasks can collectively handle all incoming events without piling up or missing any.
  4. Responsiveness (Latency): For a single event, we want to minimise the time from interrupt to task completion.

Once the environment triggers a new event, your system must respond and be ready to process another event when it arrives. 24/7, 365.

Priority Is an Indirect “Rate”

In a purely event-driven system, the system’s external event rate partially determines how frequently tasks run. By giving a higher priority to tasks handling more frequent or more critical events, you ensure they preempt lower-priority tasks, effectively matching CPU service to the real-world demand. In a sense, the environment plus the priority scheme sets the actual “rate” of execution for each tasks.

Beware

  1. Worst-Case Scenario: If multiple events occur in rapid succession or arrive simultaneously, the tasks must still complete without overrunning.
  2. Priority Inversion: If high-priority tasks block on resources held by low-priority tasks, you could see responsiveness degrade. Priority-inheritance mechanisms can mitigate that.
  3. System Saturation: If event arrival rates exceed the system’s overall capacity, tasks will eventually stack up in queues. Even with correct priorities, you can miss deadlines if CPU utilization is too high.

The “clock” is effectively the external world.

Finally, if the environment’s event rate is within your system’s capacity and tasks are prioritised appropriately, you are meeting deadlines and working in real-time.

/* comment here */