Client and backend. This class is shared: the same code is compiled into your app and into your server, so everything on this page works in both.

public class Realtime

  1. Object
  2. Realtime

Known subtypesBoardRealtime

Entry point to real-time threads: periodic tasks that run at a fixed operating-system priority, are released on an absolute clock, and are not paused by the garbage collector.

Realtime rt = Realtime.getInstance();
rt.lockMemory();                          // no page faults in a period
rt.setMemoryLimit(64L * 1024 * 1024);     // fail fast instead of thrashing
RealtimeThread motor = rt.start("motor",
        new RealtimeParameters().setPeriodNanos(1000000L).setPriority(80).setCpu(3),
        new MotorLoop());
...
Log.p(motor.getStatistics().toString());

How the collector is kept away

A real-time task allocates in setup() and never in cycle(). The build rejects an allocation that cycle() reaches, and at run time an allocation it could not see ends the steady state with a RealtimeAllocationError – so the thread never needs the collector to make room. The collector in turn never stops it for a whole cycle: collections stay concurrent while a real-time thread exists, its stack is scanned while it sleeps between periods, and it is released as soon as that one stack has been read. Normal threads run below it, the collector’s included, so a busy collector slows them, not it.

What this is and is not

On Linux with a PREEMPT_RT kernel this is firm real time: release latency in tens of microseconds, measured, not proven. It is not certified hard real time and makes no claim under any safety standard. Measure the loop on the device, under load, with RealtimeThread.getStatistics().

Platforms

  • Linux (the embedded and desktop Linux targets, the backend on Linux): every feature. Real-time scheduling needs CAP_SYS_NICE or an rtprio limit.
  • Other translated targets (iOS, macOS, Windows, the backend elsewhere): the collector isolation and the allocation check, with normal-priority threads and a relative sleep.
  • The simulator, Android, JavaScript: a best-effort Java thread with the same API, so the application runs and can be tested anywhere; there is no isolation from the collector and no allocation check at run time.

For port implementors

A port subclasses this class and overrides the protected primitives, which act on the calling thread. The defaults are the best-effort Java implementation.

Fields

public static final int FEATURE_SCHEDULING = 1Real-time scheduling (SCHED_FIFO on Linux).
public static final int FEATURE_MEMORY_LOCK = 2Locking the process’s memory so it is never paged out (lockMemory()).
public static final int FEATURE_GC_ISOLATION = 4Real-time threads are not paused by the garbage collector.
public static final int FEATURE_ALLOCATION_CHECK = 8Allocation in a cycle is detected at run time.
public static final int FEATURE_PREEMPT_RT_KERNEL = 16The kernel is a PREEMPT_RT kernel, which bounds its own latency.
public static final int FEATURE_CPU_AFFINITY = 32Threads can be pinned to a CPU.
protected static final int APPLIED_SCHEDULING = 1rawEnter(RealtimeThread, int, int, boolean) result bit: scheduling applied.
protected static final int APPLIED_AFFINITY = 2rawEnter(RealtimeThread, int, int, boolean) result bit: CPU pinned.
protected static final int APPLIED_ISOLATION = 4rawEnter(RealtimeThread, int, int, boolean) result bit: other threads moved off.

Constructors

protected Realtime()Ports construct subclasses; applications call getInstance().

Methods

public static Realtime getInstance()Returns the real-time entry point of the current platform.
public static void install(Realtime realtime)Makes realtime the instance getInstance() returns; null restores the default.
public boolean isSupported(int feature)true when the platform provides the feature, one of the FEATURE_ constants.
protected int getSupportedFeatures()Bit mask of the FEATURE_ constants this platform provides.
public RealtimeThread start(String name, RealtimeParameters params, RealtimeTask task)Starts a real-time thread running task.
public boolean lockMemory()Locks every page the process has and will have into memory, so a period never waits for one to be paged in.
public void setMemoryLimit(long bytes)Caps the memory of the process.
protected int rawEnter(RealtimeThread thread, int priority, int cpu, boolean isolate)Makes the calling thread real-time.
protected void rawLeave(RealtimeThread thread)Returns the calling thread to normal scheduling.
protected void rawStartPeriod(RealtimeThread thread, long periodNanos)Starts the periodic clock on the calling thread; the first release is one period from now.
protected int rawWaitNextPeriod(RealtimeThread thread)Sleeps the calling thread to its next release.
protected void rawFreeze(RealtimeThread thread, int budget, RealtimeAllocationError error)Enters the steady state on the calling thread: from here an allocation beyond budget per period throws error.
protected void rawThaw(RealtimeThread thread)Leaves the steady state on the calling thread.
protected void rawStatistics(RealtimeThread thread, long[] out)Copies the calling thread’s statistics into out (RealtimeStatistics.COUNT values).
protected String rawLastViolation(RealtimeThread thread)The class of the allocation that ended the calling thread’s last steady state, or null.
protected int rawLockMemory()Locks the process’s memory.
protected void rawSetMemoryLimit(long bytes, OutOfMemoryError error)Installs the memory limit; error is the instance to throw.

Inherited methods

Field details

FEATURE_SCHEDULING

public static final int FEATURE_SCHEDULING = 1
Real-time scheduling (SCHED_FIFO on Linux).

FEATURE_MEMORY_LOCK

public static final int FEATURE_MEMORY_LOCK = 2
Locking the process’s memory so it is never paged out (lockMemory()).

FEATURE_GC_ISOLATION

public static final int FEATURE_GC_ISOLATION = 4
Real-time threads are not paused by the garbage collector.

FEATURE_ALLOCATION_CHECK

public static final int FEATURE_ALLOCATION_CHECK = 8
Allocation in a cycle is detected at run time.

FEATURE_PREEMPT_RT_KERNEL

public static final int FEATURE_PREEMPT_RT_KERNEL = 16
The kernel is a PREEMPT_RT kernel, which bounds its own latency.

FEATURE_CPU_AFFINITY

public static final int FEATURE_CPU_AFFINITY = 32
Threads can be pinned to a CPU.

APPLIED_SCHEDULING

protected static final int APPLIED_SCHEDULING = 1
rawEnter(RealtimeThread, int, int, boolean) result bit: scheduling applied.

APPLIED_AFFINITY

protected static final int APPLIED_AFFINITY = 2

APPLIED_ISOLATION

protected static final int APPLIED_ISOLATION = 4
rawEnter(RealtimeThread, int, int, boolean) result bit: other threads moved off.

Constructor details

Realtime

protected Realtime()
Ports construct subclasses; applications call getInstance().

Method details

getInstance

public static Realtime getInstance()
Returns the real-time entry point of the current platform. Never null: where nothing is installed this is the best-effort Java implementation.

install

public static void install(Realtime realtime)
Makes realtime the instance getInstance() returns; null restores the default. Display installs the port’s instance when it starts and the backend installs its own, which is why this class never names Display.

isSupported

public boolean isSupported(int feature)
true when the platform provides the feature, one of the FEATURE_ constants.

getSupportedFeatures

protected int getSupportedFeatures()
Bit mask of the FEATURE_ constants this platform provides. The default provides none.

start

public RealtimeThread start(String name, RealtimeParameters params, RealtimeTask task)
Starts a real-time thread running task.

Parameters

name String
the thread’s name, for logs and debuggers
params RealtimeParameters
its scheduling; copied, so later changes do not affect it
task RealtimeTask
the work it runs

Returns

the running thread

lockMemory

public boolean lockMemory()
Locks every page the process has and will have into memory, so a period never waits for one to be paged in. Call it early: it also makes every later allocation of memory resident at once.

Returns

true when the memory was locked; false where unsupported or refused (Linux needs CAP_IPC_LOCK or a large enough memlock limit)

setMemoryLimit

public void setMemoryLimit(long bytes)

Caps the memory of the process. After a collection that leaves the process above bytes, a normal thread that asks for more memory gets an OutOfMemoryError at once, instead of waiting for collections that cannot free enough – a failure the application can handle, in place of a device that slows to a crawl. Real-time threads are never refused: they do not allocate.

The limit is on the process’s resident memory, because that is the memory a device runs out of; it includes memory the heap holds and has not returned yet. An allocation is refused when a collection leaves the process over the limit, or without waiting for one once the process is a quarter over it. Linux only; elsewhere this does nothing.

Parameters

bytes long
the limit, or 0 for none

rawEnter

protected int rawEnter(RealtimeThread thread, int priority, int cpu, boolean isolate)
Makes the calling thread real-time.

Returns

the APPLIED_ bits for what took effect, or a negative errno

rawLeave

protected void rawLeave(RealtimeThread thread)
Returns the calling thread to normal scheduling.

rawStartPeriod

protected void rawStartPeriod(RealtimeThread thread, long periodNanos)
Starts the periodic clock on the calling thread; the first release is one period from now.

rawWaitNextPeriod

protected int rawWaitNextPeriod(RealtimeThread thread)
Sleeps the calling thread to its next release.

Returns

how many releases were missed

rawFreeze

protected void rawFreeze(RealtimeThread thread, int budget, RealtimeAllocationError error)
Enters the steady state on the calling thread: from here an allocation beyond budget per period throws error. The default has no run-time check.

rawThaw

protected void rawThaw(RealtimeThread thread)
Leaves the steady state on the calling thread. Safe to call when not frozen.

rawStatistics

protected void rawStatistics(RealtimeThread thread, long[] out)
Copies the calling thread’s statistics into out (RealtimeStatistics.COUNT values).

rawLastViolation

protected String rawLastViolation(RealtimeThread thread)
The class of the allocation that ended the calling thread’s last steady state, or null.

rawLockMemory

protected int rawLockMemory()
Locks the process’s memory. Returns 0 or a negative errno; the default answers -38 (ENOSYS).

rawSetMemoryLimit

protected void rawSetMemoryLimit(long bytes, OutOfMemoryError error)
Installs the memory limit; error is the instance to throw. The default does nothing.