From a library request to a system-call result
Follow ABI dispatch, argument validation, partial results, and measured batching costs without assuming every call blocks.
On this page
The question for today
What you’ll understand
- Describe the role of the architecture ABI in dispatching a system call.
- Handle partial progress, end of input, and errors as distinct outcomes.
- Estimate batching gains while preserving operation and latency semantics.
An application asks to read a buffer, but the kernel does not receive a high-level language object labeled safe request. It receives values encoded according to an interface contract. Dispatch connects those values to an implementation; validation decides what the request is allowed to mean; the result tells the application what actually happened. Good systems code treats all three stages as part of correctness before attempting to reduce their cost.
Dispatch follows an ABI, not a portable register recipe
A system-call ABI specifies how an architecture represents the requested operation, arguments, results, and errors at the user-kernel boundary. Registers are common carriers, but their assignments and exceptional details differ across architectures and compatibility modes. A C library wrapper usually handles those details for its target. Its calling convention is not necessarily the same as the kernel's calling convention. Copying a register sequence from an unrelated machine can produce a different request or invalid arguments even when the source-level function name appears familiar.
Entry machinery establishes the kernel-side execution state before dispatch reaches an implementation. The operation number must be interpreted within the appropriate ABI, and unsupported numbers require a defined failure path. Policy mechanisms can also affect whether an operation is allowed or observed. Implementations must validate lengths, access rights, and object state; a user-supplied pointer is not a trusted kernel pointer. Appropriate access helpers handle faults, and a check does not freeze user memory that another thread can change. Copying or synchronization must match the interface's actual ownership contract. These are reasons to learn the boundary as a contract rather than memorize a particular internal function name. Kernel organization and mitigation settings evolve; a diagram of one implementation version is useful evidence for that version, not an invariant guaranteeing the same sequence or latency on every Linux installation.
The return value is part of the protocol
For a read-like byte interface, a positive result reports the number of bytes actually obtained, which can be smaller than the requested count without indicating failure. A zero result for an ordinary nonzero-length read can indicate end of input, depending on the object and interface. A negative wrapper return accompanied by an error indication describes another outcome. Write code around the documented object-specific semantics instead of assuming that a successful request always fills the entire application buffer. A stream parser may need to retain incomplete application messages across several successful reads.
An interrupted operation requires equally careful treatment. An error such as EINTR can mean interruption before progress for a particular call, while an operation that already transferred bytes may report that positive partial count. Restart rules depend on the interface and signal configuration. Advance the buffer position only by confirmed progress, preserve an application deadline across retries, and stop according to the protocol's completion condition. A retry loop that blindly resets its timeout can exceed the caller's latency budget even if each individual attempt observes a locally reasonable limit.
Batch only after preserving meaning
Reducing calls can amortize fixed overhead, but larger batches may need more buffering and can delay the first record while the batch fills. A batching interface can also have different atomicity, ordering, completion, and failure behavior. Compare completed application work under equivalent conditions. For an inference service, the relevant outcome may be replies meeting a deadline, not merely fewer entries into the kernel. Measure both CPU service and elapsed latency, document the batch policy, and retain the actual partial-completion logic after introducing a supposedly faster data path.
The queue lab offers an overload thought experiment rather than a system-call implementation. Compare separate runs with arrival rate 2 and service rate 1 versus arrival rate 2 and service rate 3. Before each run, press Reset, re-set both desired rates, predict whether the fresh four-job backlog grows or drains, then press Play or Step. Changing a control alone does not begin a new run or preserve the previous backlog as a new starting point. A real batching improvement could raise effective service capacity, but the control does not compute that improvement from an ABI or a batch size. The separate residence-time readout uses a stable M/M/1 model with Poisson arrivals and exponential service, which batching can violate. Use the lab to form a capacity question, then determine the actual answer with a workload and a measured completion contract.
Work it through
Amortize a fictional entry cost
A synthetic operation processes 1,000 records. Fixed per-call CPU overhead is 2 μs and unchanged record work is 0.5 μs. Compare one record per call with batches of 100; ignore copying differences, batch-fill delay, blocking, and partial completion.
With one record per call there are 1,000 calls. Fixed overhead is 1,000 × 2 = 2,000 μs, and record work is 1,000 × 0.5 = 500 μs, totaling 2,500 μs.
With batches of 100 there are ten calls. Fixed overhead falls to 20 μs while record work remains 500 μs, totaling 520 μs.
The modeled CPU reduction is 1,980 μs, and the modeled speedup is 2,500 / 520 ≈ 4.81. Check real batch semantics and response latency before interpreting that synthetic ratio as useful application improvement.
Batching removes most of the assumed fixed overhead here, but cannot remove the unchanged 500 μs of record work or establish real-world latency gains.
The living notebook
Explore the model
Interactive lab · queue
Ask whether a capacity change is enough
Compare separate fixed-rate runs with λ=2, μ=1 and λ=2, μ=3. For each run, press Reset, re-set both rates, predict the slope from a fresh four-job backlog, then Play or Step. A control edit retains elapsed time rather than switching rates along one trajectory. This lab neither dispatches syscalls nor computes batching costs; its M/M/1 mean requires its stated assumptions.
- Fluid backlog
- 4
- Net rate · λ − μ
- −1 /s
- M/M/1 mean residence
- 1 s
Fluid backlog starts at 4 and follows max(0, 4 + (λ − μ)t). The separate M/M/1 residence-time formula assumes Poisson arrivals, exponential service and λ < μ. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forA lower entry count is useful only when the resulting service behavior improves completed work under the required contract.
Pause & reason
Check your understanding
Your turn
Try it yourself
A fixed-length 900-byte message arrives in successful reads of 256 and 400 bytes. What buffer offset and remaining count should the next attempt use? What if that attempt reports interruption before progress?
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Accumulate only positive confirmed byte counts and keep the same overall deadline.
Compare with the solution
Confirmed progress is 656 bytes, leaving 244 bytes. The next attempt starts at offset 656 with room for 244 bytes. If the interface reports interruption before progress, neither count changes; the reader follows the documented retry policy while preserving its existing application deadline rather than granting a fresh unlimited waiting interval.
Keep the idea
Take it with you
- ABI details belong to a specific architecture and interface contract.
- Partial progress, end of input, and errors require different state transitions.
- Batching trades fixed overhead against latency, buffering, and completion semantics.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.