LinuxCNC context diagram — as published, reviewed, rebuilt

docs/src/getting-started/images/LCNC_Architecture_C1.drawio.svg, merged by PR #3781 on 2026-03-01. The working base of this page is their work: the diagram zz912 drew, shaped in review by smoe, c-morley and BsAtHome in that thread, and merged by andypugh. Both states are redrawn here from the same code, so the only differences between them are the two marked changes. The three actor boxes — operator, developers, integrator — have been dropped from both views, along with the thirteen arrows that started from them — a change of purpose, not a correction, and one zz912 has declined for his own diagram: the actors are what it was drawn to show. His answer of 2026-08-10 opens the notes below, and it settles two of the three points raised here. The third view is not that drawing at all: it is rebuilt from the source, cross-checked against the findings file, and its structure differs because the published structure does not match the code. Third sheet of the audit — the verification passes behind it, and the corrections they forced on this page itself, are recorded in the closing notes.

First two: same drawing. Red: the error zz912 accepts. Grey: raised, and declined by him. Third: redrawn from scratch.
Embedded Tabs andPanels GUIGmoccapy / Axis / Qt LinuxCNC Core Runtime Motion controller Trajectory planner Kinematics Task controller G-code interpreter Status & command IPC HAL Interface Boundary Pins . Signals . Threads . Functions INI Configuration HAL Configuration (.hal files, loadrt, nets) Integrator-defined topology HAL Modules (drivers, counters, stepgens, logic) HAL Components - Library HAL Components - Custom WizardsPNConf / Stepconf Machine Hardware (Panels, buttons,potentiometers) Machine Hardware(joints, spindles, IO, safety) Terminal halcmd / halshow / linuxcncrsh linuxcncrsh halcmd / halshow attach to HAL, not to the core 1 2 signals and components must be used for using LCNC signals and components are optional (LCNC can be used without them)
scheduling boundary — SCHED_FIFO threads inside rtapi_app, not a kernel boundary NON-REALTIME — ordinary Linux processes, no timing guarantee rtapi_app — the realtime domain Wizardspncconf / stepconf INI file[KINS] · periods limits · which GUI HAL filesloadrt · addf net · setp GUI Axis / Gmoccapy / QtVCP embedded tabs & panels export HAL pins linuxcncrshNML over the network halcmd / halshow HAL clients — hal_init() they never touch NML NML — three channels emcCommand 8192 queued · emcStatus 20480 overwritten emcError 8192 queued linuxcncsvr — its own process; owns the three NML channels milltask — the task process task controller · rs274ngc · iocontrol HAL pins (no separate EMCIO) emcmot shared segment — key 100 one command slot + mutex, commandNum → commandNumEcho, 1 s timeout status seqlock (head / tail) · error ring 32 × 1024, newest lost when full HAL — 2 MiB shared memory, key 0x48414C32 pins · signals · parameters · functions · threads servo-thread — servo_period_nsec motion-command-handler motion-controller tpmod · homemod one of 19 *kins separate modules (loadrt), called from motmod's functs both exported by motmod via hal_export_funct() pid.N.do-pid-calcs encoder · stepgen.capture-position members, not execution order — the pass opens with the driver read (addf order) base-thread created only when servo_base_ratio > 1 stepgen.make-pulses hardware drivers, in these same threads hostmot2 (Mesa) · lcec (EtherCAT) parport · and the rest Machine hardware drives · encoders · limit and home switches · spindle · field I/O

zz912's answer — 2026-08-10 — and what this page withdraws

The three observations below were put to the author of the figure on his own thread. He answered on 2026-08-10 (#3718): one he accepts as an error in his diagram, two he declines, with his reasons. They are recorded here rather than argued past, and the arguments are left standing where they were made — marked as answered, not deleted, so a reader can check the answer against what it answers.

Accepted — the terminal tools (note 1). "I agree with you here. That is an error in my diagram. If you want to prepare a PR fixing this, please do so."

Declined — the embedded panels' HAL link (note 2). "I agree that there is currently no such direct link that should be shown in the diagram. I deliberately did not draw one." His reasons, in his words. The mechanism is unsettled: "Part of the reason is that C-morley is currently working on ZMQ communication, so I think we should wait and see what becomes the preferred approach for creating and communicating with embedded panels in the future." The impression it would give: "When I was a beginner, I initially had the impression that HAL was somehow the universal solution for connecting everything to everything in LinuxCNC. I don't think that is a particularly helpful impression to give to beginners." The layering: "HAL is a realtime part of the system, whereas embedded panels are a user-interface mechanism." And the question is outside what this diagram is for: "deciding whether an Embedded Panel should communicate through HAL, ZMQ, or something else is an architectural design question that I don't think should be encoded into the C1 context diagram." This page called the omission "a real gap"; that judgement is withdrawn. The code fact underneath it — those panels exist to export HAL pins — is not in dispute, and he does not dispute it.

Declined — dropping the three actors. "Regarding the three actors, though, my intention was actually almost the opposite of yours. The Operator, Integrator and Developer are the most important parts of my context diagram." And on what removing them would do: "Removing them would make the diagram clearer as an internal technical map, but it would also remove the main purpose for which I created this particular diagram." Nothing on this page proposes that removal for his figure. The two A/B views here drop the actors because this page asks the wiring question — which is, in his words, "a different question".

1  The terminal tools sit on the wrong side of the boundary

As published, one box holds halcmd / halshow / linuxcncrsh and draws a single link — to the Core Runtime. Two of those three attach to HAL instead:

halcmd.c:107 calls hal_init(comp_name) — halcmd is a HAL component. halshow's man page: "a GUI interface to view and interact with a running HAL session", and it drives halcmd internally (halshow.tcl:825, 1224). Only linuxcncrsh commands the core — "text-mode interface for commanding LinuxCNC over the network".

This was raised in review and never resolved. smoe wrote: "The Devs may also use command line variants as a HAL interface … Examples are linuxcncrsh or halcmd." The reply added a Developers→Terminal arrow; the link to HAL was never drawn.

2  Embedded tabs and panels have no link to HAL — raised, and declined

Their entire purpose is to export HAL pins — pyvcp_widgets.py:205,209 and gladevcp/hal_widgets.py:44-45 call newpin(). As published they connect only to the GUI. On a diagram whose central organising line is the HAL Interface Boundary, this page argued that leaving out the HAL link of the one component that exists to cross it was a real gap.

zz912 has declined that, and the omission is deliberate — his reasons are quoted in the first note. The pin exports stand; the conclusion drawn from them does not. The arrow stays on the second view, in grey, as a point raised and answered — not as a defect.

Left alone on purpose — debatable, not wrong

Kinematics and Trajectory planner inside "Core Runtime". Both are RT modules loaded by loadrt (loadrt trivkins, chosen by [KINS]KINEMATICS — axis.ini:140) — that is, by what the diagram itself files under HAL Configuration (.hal files, loadrt, nets). A defensible functional grouping, but inconsistent with its own labelling.

"HAL Components – Library / Custom" feeding "HAL Modules". LinuxCNC calls both components; the split invents a hierarchy. Readable as source-versus-loaded, so confusing rather than false.

"Machine Hardware" labels two different boxes — panels and buttons on one side, joints and spindles on the other.

"Machine Hardware (joints, spindles, IO, safety)". The served figure already says joints, and it is right — the moving parts of a machine are joints, and "axes" is the conflation the findings' erratum 6 documents elsewhere. Its own .drawio source still says "(axes, spindle, IO, safety)": the two files have disagreed since #4057, where the published SVG was replaced by a hand-rebuilt one. That divergence is reported in #4423, not settled here.

The caption added during review also matters: "It is not intended to help you understand the functionality of LinuxCNC." That covers the simplifications above. It does not cover a wrong connection — showing who talks to what is precisely what this diagram sets out to do.

What dropping the three actor boxes changes — and why zz912 keeps them

Operator, Developers/Testers and Integrator were the actors of a C4 level-1 context diagram — a system in its scope, with its users and neighbouring systems. Removing them, and the thirteen arrows fanning out from them, turns this into something else: a map of the parts and how they are wired. Nothing is orphaned by their removal; every remaining box still has at least one connection.

That is a legitimate second diagram, and close to what c-morley kept asking for on both threads — "Keep it simple as it was and then build a different purpose built diagram for interrogators [sic] or users or what ever your target audience is." But it no longer answers the question the original was built to answer. zz912's stated aim was "to show how developers, integrators and operators are involved in the project. That's all." Judged as a technical map this version is clearer; judged as what it was drawn to be, the actors were the content.

zz912 answered this on 2026-08-10: he keeps the actors, because they are what the figure was drawn to show. His words are in the first note. Nothing here is a proposal to remove them from his diagram.

Worth keeping straight if any of this ever goes upstream: one marked change is an error in the published figure and its author says so; one was raised and declined; and this removal is a change of purpose. The three should not travel in the same sentence.

What changed, and why — every point checked against the source

The motion controller moved down, inside HAL. It was drawn above the HAL boundary, as a peer talking across it. It is a HAL function: motion.c:1030,1037 export motion-controller and motion-command-handler through hal_export_funct(), and the config file does addf motion-controller servo-thread. It does not talk across HAL — it runs inside it. tpmod, homemod and the kinematics module are called from within that function, so they moved with it. Homing was missing altogether and is now shown: homemod.c:23 has its own rtapi_app_main.

The scheduling boundary is drawn. The published figure has none, and puts task and motion in one box. They are different processes in different domains. The label says scheduling, not kernel: on the default uspace build over PREEMPT_RT, "realtime" components are SCHED_FIFO user threads inside rtapi_app. That distinction is erratum 9 of the findings file.

The two IPC mechanisms are separated. One label — "Status & command IPC" — covered both. Above the boundary, NML: three channels, emcCommand 8192 queued, emcStatus 20480 overwritten, emcError 8192 queued. Across the boundary, something else entirely: the emcmot segment at key 100 — a single command slot under a mutex, with a commandNum → commandNumEcho handshake and a 1 s timeout, a seqlock for status, and a 32 × 1024 error ring that refuses the newest message when full. Not a queue, and not NML.

The terminal tools are split. halcmd and halshow attach to HAL and never touch NML; only linuxcncrsh speaks NML. Its line runs from userspace straight down into the HAL block, which also shows something the original hid: HAL shared memory is reachable from ordinary processes.

Smaller ones. linuxcncsvr now appears — and as its own process, which it is: the start script launches it before realtime is loaded (scripts/linuxcnc.in:803, under the comment "it owns/creates the NML buffers", :795) and task separately later (:824); the kill list names linuxcncsvr milltask side by side (:678). The milltask box states that iocontrol's pins live there and that no separate EMCIO process exists. The base thread carries its real condition, servo_base_ratio > 1, not a non-zero period. HAL's label includes parameters, which the original omitted.

Everything here traces to the findings file — errata 3, 5, 6, 8, 9, 29, 31, 32, 33, and the §2 material on the shared segment, the seqlock and the servo cycle. Nothing was drawn from a memory of how LinuxCNC ought to work.

Corrections to this page — 2026-08-06

A verification pass — four passes, separate oracles: the cited lines re-read in the pinned clone, the published .drawio's edge graph extracted, adversarial greps on the gates, the review-thread quotes re-read verbatim with gh — confirmed every code claim above except one, and caught three fidelity slips. Recorded here rather than silently repaired:

1. The rebuilt view drew linuxcncsvr inside "The LinuxCNC task process". It is a separate process — the start script runs it at step 4.3.1 ("it owns/creates the NML buffers", scripts/linuxcnc.in:795) and task at 4.3.7, and the kill list names linuxcncsvr milltask side by side (:678). The same class of error this page criticises — a process boundary drawn wrong. Now two boxes.

2. The c-morley quotation silently corrected his "interrogators" to "integrators". Restored verbatim with [sic] — when quoting, the words bind.

3. The as-published view wrote "(joints, spindles, IO, safety)" where the merged file says "(axes, spindle, IO, safety)" — an unmarked correction, contradicting this page's own promise that the only A/B differences are the flagged ones. Published wording restored; the joints question moved to the "left alone" list.

4. Wizard names: the A/B views now match the published PNCconf / Stepconf; the rebuilt view uses the command names pncconf / stepconf (src/emc/usr_intf/pncconf/Submakefile:3). Two wording fixes besides: tpmod/homemod/kins are "separate modules (loadrt), called from motmod's functs" — "linked into" was loose — and the servo-thread box now says its contents are members, not execution order.

Corrections to this page — 2026-08-19

zz912 answered the three observations on 2026-08-10. Until today this page went on serving two of them as though they were still open: it called the missing panels → HAL link a real gap, and it weighed the removal of the three actors as a live option. Sending him here would have made him read, as current, arguments he had already answered — with his reasons — nine days earlier.

What changed: his answer now opens the notes, in his own words and linked to the comment; the two declined points are marked as declined at the place where they are made; and the second marked change is drawn in grey, badge included, so the accepted error and the declined observation are no longer the same colour. The page is titled as published, reviewed, rebuilt rather than vs corrected, because one of the two marks is not a correction.

Nothing was deleted. The arguments stand where they were made, which is what lets a reader check the answer against what it answers.

Later the same day, two more — and they are of a worse kind. Correction 3 above says the as-published view was restored to the merged file's "(axes, spindle, IO, safety)", and correction 4 says the wizard names were matched to the published PNCconf / Stepconf. Both are false. The figure the documentation actually serves reads "(joints, spindles, IO, safety)" and PNConf / Stepconf. The published state had been judged on the .drawio source instead of the SVG served from it — the very fault this page charges elsewhere, committed here twice. The two drawn labels now reproduce what is served, PNConf and its dropped letter included; the wizard's own name is pncconf.

Corrections 3 and 4 are left exactly as they were written. They record what was done on 2026-08-06, and rewriting them would remove the mistake instead of showing it.

Two smaller ones in the answer note above. zz912's ZMQ reason was quoted from "C-morley is currently…", cutting the "Part of the reason is that" that opens his sentence — a hedge, and dropping it made one reason among several read as the reason. And a fourth reason of his was left out while the text called them three: the impression HAL gives a beginner, which carries the most weight of the four, since this figure lives in the Getting Started chapter. All four are now quoted, whole.

Redrawn from the published SVG's own coordinates, so the layout matches closely enough to compare by flipping. It is a faithful redraw, not a pixel copy — open the original alongside if precision matters: docs/src/getting-started/images/LCNC_Architecture_C1.drawio.svg. Everything else in the figure checked out: the role structure, the wizard flows, operator ↔ GUI solid against operator ↔ physical panel dashed, integrator → hardware, HAL Modules ↔ Machine Hardware, Core ↔ HAL boundary, and the solid/dashed legend applied consistently throughout. Verified line by line against the pinned clone (caa13ca6ae) and corrected on 2026-08-06 — see the closing notes: a second pass followed on 2026-08-19.