2 Punkte von GN⁺ 2023-11-17 | 1 Kommentare | Auf WhatsApp teilen
  • Die Unterstützung von Linux für Echtzeit-Preemption wartet seit fast 20 Jahren auf die Aufnahme in den Mainline-Kernel; Thomas Gleixner sagte auf der Linux Plumbers Conference 2023, dass das letzte große Hindernis printk() sei
  • Ziel ist, dass Prozesse mit der höchsten Priorität mit vorhersehbar kurzer Latenz ausgeführt werden können; dafür wurden über lange Zeit viele Kernbereiche des Kernels neu geschrieben
  • printk() kann in praktisch jedem Kontext aufgerufen werden und ist daher weit komplizierter als einfache Log-Ausgabe; die aktuelle synchron arbeitende Ausgabe kollidiert mit den Echtzeit-Latenzzielen
  • Seit 2018 sind rund 300 Patches upstream gelandet oder warten in linux-next; die verbleibenden Aufgaben sind ein Handover-Mechanismus für dringende Meldungen und die sichere Behandlung von Konsolentreibern
  • Wenn die Bereinigung von printk() abgeschlossen ist und der restliche Echtzeit-Code in linux-next bereitsteht, wäre sogar eine Zusammenführung im selben Merge Window möglich, aber Gleixner will keine Fertigstellungstermine mehr vorhersagen

Fast 20 Jahre Arbeit an Echtzeit-Preemption

  • Linux-Echtzeitunterstützung tauchte bei LWN erstmals 2004 auf und wirkte lange so, als sei sie „fast fertig“
  • LWN verwendete schon 2009 den Titel the realtime preemption endgame, doch auf der Linux Plumbers Conference 2023 sagte Gleixner, dass das Ende nun wirklich nahe sei
  • Für Gleixner persönlich ist es eine Aufgabe von fast 25 Jahren
    • Er begann 1999 mit der Arbeit an Linux-Echtzeitunterstützung
    • Das Projekt selbst läuft inzwischen seit fast 20 Jahren
  • Er sagte, nach Abschluss der Arbeit werde es „a big party“ geben, aber als letzte große Hürde bleibt printk()

Welche Latenzen Echtzeit-Preemption verringern soll

  • Das Ziel von Echtzeit-Preemption ist, dass Prozesse mit der höchsten Priorität stets mit minimaler und vorhersehbarer Latenz ausgeführt werden können
  • Dafür muss der Kernel in möglichst vielen Situationen präemptierbar sein; Ausnahmen müssen auf einen engen und klar definierten Bereich beschränkt werden
  • Das Grundprinzip steht seit Langem fest, doch die Lösung der Detailprobleme hat viel Zeit gekostet
  • Dabei wurden viele Teile des Kernel-Kerns neu geschrieben, und der Nutzen geht weit über Echtzeit-Anwendungsfälle hinaus und kommt dem gesamten Kernel zugute

Warum printk() das letzte Hindernis ist

  • Wenn Kernel-Code Meldungen an Konsole oder Logs senden muss, ruft er printk() oder darauf aufbauende Funktionen auf
  • Das wirkt wie eine einfache Ausgabe, aber printk() muss in nahezu jedem Kontext funktionieren
    • Es kann sogar in non-maskable interrupt-Handlern aufgerufen werden
    • Es kann innerhalb eines anderen printk()-Aufrufs erneut aufgerufen werden
    • Bei Systemabstürzen kann die ausgegebene Information entscheidend sein, daher lässt sich der Aufrufkontext kaum einschränken
  • Diese Anforderungen führen dazu, dass bei printk() Probleme rund um Parallelität, Locking und Treiberverarbeitung komplex miteinander verflochten sind
  • Im aktuellen Kernel ist printk() vollständig synchron aufgebaut
    • Der Aufruf kehrt erst zurück, wenn die Meldung an alle konfigurierten Ziele übertragen wurde
    • Gleixner bezeichnete diese Struktur als „stupid“
    • Besonders während des Bootens ist der Großteil der Ausgabe oft bloß Rauschen, dennoch muss gewartet werden, bis alles übertragen ist
  • Diese Wartezeit steht in direktem Widerspruch zu den Latenzen, die Echtzeitarbeit eigentlich verringern soll
  • Echtzeitentwickler haben die printk()-Ausgabe schon vor langer Zeit in einen separaten Thread verschoben, um sie asynchron zu machen, doch dieser Code war eher eine Sammlung von Hacks als eine grundlegende Lösung

Überarbeitung von printk() seit 2018

  • Das printk()-Problem wird seit 2018 ernsthaft angegangen; rund 300 Patches sind upstream gelandet oder warten in linux-next
  • Derzeit laufen die letzten drei Patch-Serien, die für den Abschluss der Arbeit nötig sind
  • Eine der schwierigsten Detailaufgaben ist der Handover-Mechanismus
    • Wenn der Kernel dringende Meldungen wie Crash-Informationen ausgeben muss, kann es nötig sein, die Kontrolle über eine Konsole zu übernehmen, die gerade Meldungen mit niedriger Priorität ausgibt
    • Das in jedem Kontext sicher zu tun, ist nicht einfach
  • Eine weitere Aufgabe ist das Markieren von Konsolentreibern, die sich in bestimmten Kontexten nicht sicher verwenden lassen
    • Wenn etwa während eines non-maskable interrupt eine Meldung ausgegeben werden soll, dafür aber ein Umschalten des Videomodus nötig wäre, kann das nicht funktionieren
  • Gleixner sagte, dass sich das grundlegende Konzept im letzten Jahr nicht geändert habe
    • Im Kernel gibt es 76 Konsolentreiber, die angepasst werden müssen
    • Der Handover-Code wurde so geändert, dass nicht alle Treiber auf einmal korrigiert werden müssen, sondern einzeln aktualisiert werden können
    • Weitere Diskussionen zur jüngsten printk()-Arbeit gibt es in diesem Artikel

Asynchrone Ausgabe und Bedingungen für die Mainline-Zusammenführung

  • Auf die Frage von Masami Hiramatsu, welche Kernel-Meldungen synchron ausgegeben werden müssten, antwortete Gleixner, dass fast alles asynchron werden solle
  • Asynchrone Ausgabe reduziert die durch printk()-Aufrufe entstehende Latenz und ermöglicht einen separaten Kernel-Thread pro Konsole
    • So kann eine schnelle Konsole in ihrem eigenen Tempo arbeiten, ohne auf die langsamste Konsole warten zu müssen
  • Der Code wurde so geändert, dass wichtige Meldungen vollständig in den Message-Buffer kopiert werden, bevor die erste Zeile ausgegeben wird
    • Das ist eine Schutzmaßnahme für den Fall, dass ein fehlerhafter Konsolentreiber das gesamte System beschädigt
  • Für eine sicherere Ausgabereihenfolge wird zuerst auf bekanntermaßen sichere Konsolen geschrieben
    • Wenn es zum Beispiel einen persistent-memory store gibt, wird die Meldung zuerst dort gespeichert, bevor sie an ein physisches Gerät gesendet wird
    • So bleibt die Ausgabe erhalten, selbst wenn ein fehlerhafter Treiber das System zum Absturz bringt
  • Gleixner sagte, dass das Ziel zwar nahe sei, printk() aber schwer vorherzusagen bleibe, weshalb er keine Fertigstellungstermine mehr nennen wolle
  • Dennoch hoffe er, dass der restliche Echtzeit-Preemption-Code noch vor dem 20. Jahrestag Ende 2024 in die Mainline aufgenommen werde
  • Auf die Frage von Clark Williams, ob der restliche Echtzeit-Code nach dem Upstreaming der printk()-Patches im selben Merge Window aufgenommen werde, antwortete Gleixner bedingt mit „yes“
    • Wenn der gesamte Code in linux-next staged ist und bereit aussieht, könnte man es versuchen

1 Kommentare

 
GN⁺ 2023-11-17
Meinungen auf Hacker News
  • QNX macht das seit Jahrzehnten richtig. Der Mikrokernel hat für alles, was er tut, eine Obergrenze, und der Code umfasst nur einige Zehntausend Zeilen.
    Der Mikrokernel kümmert sich nur um Speicherallokation, CPU-Dispatching und Nachrichtenübermittlung zwischen Prozessen. Alles Weitere, einschließlich Treibern und Loggern, läuft im Userspace und kann von Threads mit höherer Priorität präemptiert werden.
    Der QNX-Kernel verarbeitet keine Strings. Kein Parsing, keine Formatierung, keine Nachrichten. Linux ist für Echtzeit zu aufgebläht geworden, und die Architektur passt grundsätzlich nicht zu Echtzeit, weil Millionen Zeilen Kernel-Code vollständig präemptierbar gemacht werden müssen. Deshalb hat die Behebung 20 Jahre gedauert.

    • Ein modernes Beispiel ist seL4. Soweit ich weiß, verwendet es keine dynamische Speicherallokation und ist für mehrere Eigenschaften formal verifiziert.
      Der größte Beitrag zum Kernel-Design dürfte vermutlich die durchgängige Nutzung von Capabilities sein, um Kontrolle sicher und zugleich flexibel in den Userspace auszulagern.
    • Wird QNX nicht in Infotainment-Systemen von Autos eingesetzt? Mich würde interessieren, wo sonst noch.
      Die Aufblähung des Kernels an sich stört mich nicht besonders. In Linux fließt viel Entwicklungszeit, und auch wenn der Desktop nicht so hohe Priorität hat wie Server, dürfte Arbeit an einem performanten Kernel für Bereiche wie mobile Geräte auch Desktop-Nutzern zugutekommen.
    • Der aktuelle SDP-8-Kernel hat einschließlich Kommentaren und Makefiles 15.331 Zeilen.
    • Das wirkt wie eine gut strukturierte main-Funktion in C oder einer C-ähnlichen Sprache. main koordiniert nur Aufrufe anderer Funktionen; hier initialisiert der QNX-Kernel zwar weniger, aber das Grundkonzept ist ähnlich.
      Ich bin kein Kernel-Entwickler, aber diese Art, es einfach zu halten, wirkt gut.
    • Rund 90 % der „Millionen Zeilen Kernel“ sind Gerätetreiber. Wenn es auf beliebiger Hardware laufen soll, braucht man sie am Ende auch bei einem Mikrokernel.
  • Es gibt ein Beispiel dafür, wie der Kernel selbst in einem sterbenden System noch irgendwie versucht, Logmeldungen auszugeben, und wie das in realen Produktionsumgebungen genutzt wird.
    https://netflixtechblog.com/kubernetes-and-kernel-panics-ed6...

  • Ich frage mich, ob sich damit einige Hardware-/Software-Kombinationen, die für Echtzeit gebaut wurden, ziemlich gut ersetzen lassen. Inzwischen gibt es viele günstige, stromsparende und hoch getaktete ARM- und x86-Chips.
    Da die Taktraten so hoch sind, könnte es oft weniger wichtig sein, perfekte Echtzeitfähigkeit zu haben, weil selbst bei Ausreißern noch viele freie Zyklen übrig sind. Ich weiß, dass das weder elegant noch effizient ist, aber manchmal schlägt Standardware eben Präzision.

    • Aufgaben, die harte Echtzeit benötigen, lassen sich nicht mit „selbst wenn etwas verpasst wird, gibt es viele freie Zyklen“ zufriedenstellen. Es ist auch nicht nur eine Frage von CPU-Zyklen.
      Eine einzige schlecht gebaute Aufgabe kann den Kernel blockieren und daran hindern, nützliche Arbeit zu leisten. Der Kern harter Echtzeit ist: „Nichts kann die Ausführung dieser wichtigen Aufgabe verhindern.“ In der Automobil- oder Luft- und Raumfahrt müssen Steuerungssysteme unter allen Umständen laufen.
    • Anwendungen mit echten Echtzeitanforderungen haben meist so strenge Anforderungen, dass sie nicht einmal eine winzige Ausfallwahrscheinlichkeit tolerieren können. Man denke an Avionik, Medizingeräte, Autos oder militärische Anwendungen.
      Wenn man wirklich Echtzeit braucht, dann braucht man sie wirklich; „nah genug dran“ gibt es nicht. Das ist allerdings nur mein Eindruck als Außenstehender.
    • Wenn man Echtzeitanwendungen mit stromsparenden, hoch getakteten ARM-Chips baut, verwendet man überhaupt kein Betriebssystem. Für solche Zwecke zieht man x86 ebenfalls nicht in Betracht.
      Ein Betriebssystem stört zu stark, selbst wenn es ein RTOS ist. Ich weiß nicht, was diese Änderung daran ändern wird. Es hängt allerdings von der Anwendung ab, und es gibt viele Fälle, die nur „nahezu Echtzeit“ brauchen; dafür könnte es nützlich sein.
    • Stimmt, aber das wird die Notwendigkeit dedizierter Kerne nicht auf magische Weise beseitigen. Wahrscheinlich läuft es eher darauf hinaus, dem Scheduler anzuweisen, nicht präemptierbare Echtzeitaufgaben nur auf einem LITTLE-Core zu platzieren.
  • Die Diskussion hier konzentriert sich auf die Unterscheidung zwischen „harten“ und „weichen“ Echtzeitanwendungen. Für harte Echtzeit will man vermutlich von vornherein kein Allzweckbetriebssystem wie Linux verwenden, und bei weicher Echtzeit wie Videokonferenzen oder Audiowiedergabe ist es keine Katastrophe, wenn es gelegentlich ruckelt oder ein paar Frames ausfallen.
    Die Argumentation lautet, dass RT Linux für solche weichen Echtzeitfälle eine starke Lösung sein wird. Die vorgeschlagenen weichen Anwendungsfälle sind aber schon heute mit Embedded Linux möglich. Niedriglatente Software-Video- oder Audiowiedergabe war nicht unmöglich; das ging auch schon vor 20 Jahren.
    Das Problem entsteht, wenn auf einem ausgelasteten System häufig nicht präemptierbares I/O dazwischenfunkt, doch in Embedded-Umgebungen kommt das selten vor. Es gibt überzeugende Gründe, den Kernel vollständig präemptierbar zu machen und mehr Kontrolle über das Scheduling zu geben, aber das hat wenig mit der Frage zu tun, ob Linux minimale Echtzeitbetriebssysteme oder Bare-Metal-Code ersetzen sollte.
    Es ist eher gute Hygiene und führt auch bei Nicht-Echtzeitanwendungen zu einem Betriebssystem, das unter Last besser funktioniert.

  • Das sind gute Nachrichten, aber selbst wenn der Linux-Kernel echtzeitfähig wird, ist die Hardware wegen Caches und komplexer Magie im Inneren der CPU mit hoher Wahrscheinlichkeit nicht echtzeitfähig.
    Große, komplexe Hardware passt nicht wirklich zu echter Echtzeit. Deshalb beschäftigen sich AbsInt und Tools zur Worst-Case Execution Time (WCET) meist mit einfachen CPU-Architekturen. 8051 wird wirklich ewig weiterleben. Nebenbei gibt es auch Zephyr RTOS.

    • Soweit ich weiß, verhindern die Funktionen moderner CPUs den Einsatz in Echtzeit nicht. Solange etwas eine Obergrenze hat und ableitbar ist, kann man es zum Bau eines Echtzeitsystems verwenden.
      Man nimmt einfach an, dass es keinerlei Cache-Hits gibt, maximale Last herrscht usw. Wenn man eine obere Schranke für die benötigte Zeit setzen kann, ist es in Ordnung.
    • Bei „großen“ Boards auf Mikrocontroller-Niveau wie dem Raspberry Pi halte ich das für ziemlich nützlich. Dort gibt es eine Art Echtzeitkultur, und selbst wenn man kein Bit-Banging direkt mit der CPU macht, passiert von außen betrachtet alles rechtzeitig.
      Timer können Quadratur-Encoder-Eingaben entgegennehmen und nur beim Überlauf einen Interrupt senden, oder man kann das GPIO-System an DMA anbinden und ohne CPU-Eingriff Speicher auf Ausgangspins streamen. Auch Streaming an einen DAC oder DMA-Transfers von einem ADC in den Speicher sind möglich. Solche Dinge umgehen für vorhersagbare Latenzen oft den Cache.
    • SpaceX verwendet x86-Prozessoren in Raketen. Auch der kleine Drohnenhelikopter, den NASA zum Mars geschickt hat, nutzt einen „ziemlich großen“ ARM-Core, der sogar ein altes Android ausführen könnte.
    • Die Aussage, dass große, komplexe Hardware nicht für echte Echtzeit geeignet sei, stimmt nicht unbedingt. Es gibt fortgeschrittene Echtzeit-Cores wie den Arm Cortex-R82.
      Tatsächlich müssen viele Echtzeitsysteme immer weiter wachsende Sensordaten verarbeiten und aggregieren und werden deshalb zunehmend leistungsfähiger.
    • Der 68000 ist der wahre König der Echtzeit.
  • Als Berufsanfänger habe ich frustrierend viele Vorstellungsgespräche erlebt, in denen die Interviewer nicht wussten, was Echtzeit eigentlich bedeutet. Viele übersehen das im Artikel erwähnte Konzept „und vorhersagbare Latenz“ und scheinen Echtzeit einfach als „schnell“ zu verstehen.

    • Den Teil mit „minimal“ würde ich sogar ganz streichen. Der Kern von Echtzeit ist, dass es für eine Aufgabe eine vorhersagbare Obergrenze gibt. Das kann bedeuten, dass sie im Durchschnitt langsamer ist als ein Nicht-Echtzeitsystem.
      Wenn man ein Bremssystem im Auto steuert, kann „durchschnittliche Latenz 50 ms, maximal 80 ms“ akzeptabel sein, „durchschnittliche Latenz 1 ms, aber beliebig lang und möglicherweise mehrere Sekunden“ dagegen nicht.
    • Wie der alte Spruch sagt: „real time“ ist nicht „real fast“. Die Unterscheidung zwischen Hard Real-Time und Soft Real-Time verwischt das zwar etwas, aber ich denke, dass auch viele Softwareentwickler nicht wirklich verstehen, was Echtzeit tatsächlich ist.
  • Synchrones Logging hat wieder einmal Probleme verursacht. In meiner Firma hatten wir etwas Ähnliches wegen GLOG (Googles Logging-Bibliothek); wenn stdout zum Beispiel eine Datei ist, kann man bei Disk-I/O blockieren.
    Wenn unser Service länger als 100 ms stehen blieb, war in 90–99 % der Fälle GLOG die Ursache.

    • Über Logging führe ich mit Kollegen oft solche Gespräche: „Es gibt eine Best-Effort-API und eine API mit garantierter Zustellung.“ „Wir wollen garantierte Zustellung!“ „Wenn das Logging-Interface mit garantierter Zustellung offline oder langsam ist, kann es zu einem Serviceausfall kommen. Ist das okay?“ „Nein, Ausfälle dürfen nicht passieren!“
      „Was machen Sie, wenn etwas unbedingt geloggt werden muss, aber nicht geloggt werden kann?“ Heutzutage verweise ich einfach auf das CAP-Theorem und sage, dass Logging wie jedes andere verteilte System ist. Vielleicht weil es einen Wikipedia-Artikel mit einem Dreiecksdiagramm und dem Wort „Theorem“ gibt, akzeptieren die Leute das eher.
    • Einmal kam unsere gesamte Produktionsumgebung zum Stillstand, weil der syslog-Server stehen geblieben war. Wir schoben Logs per TCP hinein, und dieses Blocking breitete sich auf die gesamte Produktion aus.
      Danach stellten wir auf UDP-Übertragung um. Ein paar Logs zu verlieren ist besser, als die gesamte Produktion zu verlieren.
    • Auch bei einer $MSFT-Logging-Bibliothek gab es ein Problem der Sorte „die Logging-Bibliothek macht alles kaputt“. Man stelle sich vor, 100 Threads hätten jeweils einen 300 MB großen Logging-Puffer.
      Natürlich hat das den Speicher zerlegt, und selbst auf der teuersten SKU von Azure App Service stürzte der Server ab.
    • Wenn die Verfügbarkeit eines Produkts von ±100 ms abhängt, ist es grundlegend falsch entworfen, und das ist nicht die Schuld der Logging-Bibliothek. Nutzer werden sich nicht darum kümmern, ob es nach dem Drücken eines Buttons 100 ms länger dauert, bis etwas fertig ist.
  • Das weckt sofort alte Erinnerungen. Vor etwa 17–18 Jahren habe ich einen Kernel für Debian mit RT_PREEMPT kompiliert, um ihn für wissenschaftliche Geräte zu verwenden, die engeres Timing brauchten.
    Latenz und Jitter waren sehr beeindruckend. Danach habe ich kaum noch darüber nachgedacht, aber wenn man mit einem Raspberry Pi Embedded-Anwendungen baut und nicht auf einen Mikrocontroller mit RTOS wechseln möchte, dürfte es viele Einsatzmöglichkeiten geben.

    • Interessant, dass du den Raspberry Pi erwähnst. Vor ein oder zwei Tagen habe ich gelesen, dass RpiOS auf einem RTOS startet und läuft.
      Besonders interessant fand ich das, weil ich früher schon einmal den Vorschlag gesehen hatte, Linux als Task eines RTOS laufen zu lassen. Dinge, die harte Echtzeit-Deadlines brauchen, laufen dann im RTOS und bleiben unbeeinflusst von Latenzen, die das virtuelle Speichersystem verursachen kann. Ich erinnere mich nicht, ob das nur eine Idee war oder tatsächlich implementiert wurde, und ich habe auch die Erwähnung, dass RpiOS auf einem RTOS läuft, nur einmal gesehen, daher bin ich neugierig.
  • Ich frage mich, was das für normale Nutzer bedeutet. Ist das eine Funktion, die man nur in sehr speziellen Situationen aktiviert, oder kann sie auch der breiten Masse ein reaktionsschnelleres System bringen?

    • Soweit ich es verstehe, macht Echtzeit das System langsamer. Damit es echtzeitfähig wird, muss man allem Zeitbudgets zuweisen.
      Jede Aufgabe bekommt ein Budget X und darf es nicht überschreiten. Wenn der Best Case schnell ist, der Worst Case aber langsam, heißt das, dass das System immer vom Worst Case ausgehen muss.
    • RT verbessert Latenz nicht zwangsläufig, sondern gibt bestimmten Aufgaben eine feste Obergrenze. Die Arbeit, die nötig ist, um RT möglich zu machen, kann die Latenz im Normalfall aber durchaus verbessern.
      Das Vermeiden synchroner printk()-Aufrufe ist genau so ein Beispiel und sollte die Latenz unter Last verbessern, auch wenn RT nicht aktiviert ist. Ich denke, ein vollständig upstream integrierter RT-Kernel wird sich nicht anders verhalten als ein normaler Kernel, solange nicht tatsächlich RT-Prozesse laufen. Der Grund, warum das Upstreaming so lange gedauert hat, war, dass Kompromisse nötig waren, um RT zu ermöglichen; dem Artikel zufolge sind davon inzwischen nicht mehr viele übrig.
    • Wenn mit „normalen“ Nutzern Desktop-Nutzer gemeint sind, ändert sich nicht viel. Für eingebettete Geräte wie industrielle Steuerungen und Telekommunikationsausrüstung ist das aber eine große Sache.
      Denn damit kann man einen aktuellen Mainline-Kernel verwenden, auch wenn Echtzeit-Scheduling benötigt wird.
    • Nach meinem Verständnis wird Linux damit zu einer Option in Situationen, in denen ein RTOS gebraucht wird. Es ist für kritische Systeme wie Luftfahrt oder Medizingeräte gedacht und hat für normale Nutzer kaum Auswirkungen.
    • Die häufigsten Desktop-Endnutzer, die davon profitieren könnten, sind Leute, die Audioarbeit machen. Dort können Latenz und insbesondere Jitter ziemlich problematisch sein.
  • Ich frage mich, was ihr von Xenomai[1] haltet. Ich nutze es seit Jahren problemlos.
    Auf dem BeagleBone Black liegt der Jitter normalerweise im Bereich von einigen hundert Nanosekunden, und ich würde es als „harte“ Echtzeit ansehen. Man kann periodische Aufgaben im Bereich von einigen Dutzend Mikrosekunden schedulen, ohne jemals eine Deadline zu verpassen.
    Im Gegensatz zu Real-Time Linux, das Linux selbst präemptierbar machen will, ist Xenomai im Grunde ein eigener Kernel und führt Linux als Aufgabe darüber aus. Es stellt eine ABI bereit, über die benutzerdefinierte Aufgaben neben Linux oder mit höherer Priorität laufen können. So lässt sich zum Beispiel das printk()-Problem umgehen: Xenomai kümmert sich nicht darum und führt bereitwillig einen Kontextwechsel aus printk heraus durch, um die Nutzeraufgabe auszuführen.
    Der Nachteil ist, dass man im Xenomai-Kontext keine normalen Systemaufrufe machen kann. Man kann es zwar, aber natürlich zerstört das das Echtzeitmodell. Wenn man zum Beispiel innerhalb einer Xenomai-Aufgabe printf() oder malloc() aufruft, ist das nicht präemptierbar. Die Xenomai-ABI bildet vieles von dem nach, was man an Systemaufrufen brauchen könnte, und wenn man damit zufrieden ist, Heap-Allokation selbst zu handhaben, funktioniert das sehr gut.
    [1]: https://xenomai.org/