Skip to content

sys/stdio: add stdio_notify to emit callback on write#22429

Open
basilfx wants to merge 5 commits into
RIOT-OS:masterfrom
basilfx:feature/stdin_notify
Open

sys/stdio: add stdio_notify to emit callback on write#22429
basilfx wants to merge 5 commits into
RIOT-OS:masterfrom
basilfx:feature/stdin_notify

Conversation

@basilfx

@basilfx basilfx commented Jun 29, 2026

Copy link
Copy Markdown
Member

Contribution description

For #22350 I need to be able to execute scheduled work on the same thread that runs and executes the REPL. With the stdio module proving an stdin_isrpipe, this is not possible, unless you run a second thread to read and rebuffer, then waking up the main thread with something like thread flags. This definitely costs more memory and flash than this proposed solution.

After some experimentation, I came up with stdio_notify. This provides a way to register a write callback, that can be used in an application for aforementioned reason.

I made three deliberate choices (which are not set in stone though):

  • I did not implement this as part of isrpipe, which I could have done too. With sys/isrpipe: add convenience helpers to improve sys/stdio #22426 providing isrpipe_available, this would be feasible. However, if you have the option to choose for isrpipe to begin with, then there are probably other methods to solve the same issue. With the stdio module, you cannot. It keeps isrpipe lightweight.
  • I only add support for a single callback, because stdin is typically read by a single consumer.
  • I debated whether it should be called stdio_notify or stdin_notify, but given that stdio_available is not called stdio_stdin_available, I went with stdio_notify.

stdio backends now have to route incoming bytes via stdio_rx_write()/stdio_rx_write_one(). When stdio_notify is disabled, it inlines directly. Public access to stdin_isrpipe has been marked as deprecated, and writing to it directly will not invoke the callback (which is still backwards compatible when disable). I set it to 2027.01 for now.

Testing procedure

A test application has been provided in tests/sys/stdio_notify, which exactly shows one of its main intended uses.

Issues/PRs references

This PR builds for stdio_uart, but not for others due to #22424. #22426 was split off as another improvement.

Declaration of AI-Tools / LLMs usage:

AI-Tools / LLMs that were used are:

  • Claude Opus 4.8 for documentation and test generation
  • Claude Opus 4.8 code review

@basilfx basilfx added Type: new feature The issue requests / The PR implemements a new feature for RIOT State: waiting for other PR State: The PR requires another PR to be merged first CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Jun 29, 2026
@github-actions github-actions Bot added Platform: native Platform: This PR/issue effects the native platform Area: network Area: Networking Area: doc Area: Documentation Area: tests Area: tests and testing framework Area: build system Area: Build system Area: pkg Area: External package ports Area: drivers Area: Device drivers Platform: ESP Platform: This PR/issue effects ESP-based platforms Area: cpu Area: CPU/MCU ports Area: USB Area: Universal Serial Bus Area: sys Area: System labels Jun 29, 2026
@riot-ci

riot-ci commented Jun 29, 2026

Copy link
Copy Markdown

Murdock results

FAILED

9d2b82e fixup! tests/sys/stdio_notify: add test application

Success Failures Total Runtime
10516 0 11083 09m:42s

Artifacts

@basilfx

basilfx commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

The failing test is likely a consequence of what #22424 fixes.

@mguetschow mguetschow left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I think this is a very useful addition - I've run into similar problems before while using the RIOT shell module which also unconditionally blocks right now. May be a nice follow-up to enhance the shell module so that it does not necessarily block the main thread from doing anything else.

Regarding your three choices:

  • I did not implement this as part of isrpipe, which I could have done too. With #22426 providing isrpipe_available, this would be feasible. However, if you have the option to choose for isrpipe to begin with, then there are probably other methods to solve the same issue. With the stdio module, you cannot. It keeps isrpipe lightweight.

Agree to your reasoning.

  • I only add support for a single callback, because stdin is typically read by a single consumer.

True, and it wouldn't be very helpful for a second consumer to be woken up if stdin is drained by the time it is scheduled.

  • I debated whether it should be called stdio_notify or stdin_notify, but given that stdio_available is not called stdio_stdin_available, I went with stdio_notify.

Also +1

I haven't tested it yet, so no formal approval yet - and we should definitely hold this back until after hard feature freeze anyhow.

Comment thread tests/sys/stdio_notify/tests/01-run.py
@basilfx basilfx added the Process: blocked by feature freeze Integration Process: The impact of this PR is too high for merging it during soft feature freeze. label Jun 30, 2026
basilfx added 4 commits June 30, 2026 23:33
Route all received stdin data through new stdio_rx_write()/
stdio_rx_write_one() helpers and add stdio_set_notify(), which
registers a callback fired from those helpers once data is pushed to
stdin. This also deprecates the direct use of isrpipe_stdin, which
improves on hiding implementation details as well.

The callback must assume to run in ISR context and must be
non-blocking. It is gated behind the stdio_notify pseudomodule and
adds no overhead when the module is not used.

Typical use-case for this feature is a consumer thread that also needs
to wake up on other sources, for instance on thread flags. With this
module, the consumer can register an appropriate callback, and handle
it accordingly.
Replace direct access to stdin_isrpipe with new helpers, which also take
care of the notification callback when enabled.
This application demonstrates the main/intended use of the stdio_notify
module: one consumer that has multiple reasons to be unblocked while
reading from stdio.
@basilfx basilfx force-pushed the feature/stdin_notify branch from 717edc4 to 7fb3488 Compare June 30, 2026 21:34
Comment thread tests/sys/stdio_notify/tests/01-run.py Outdated
@mguetschow

Copy link
Copy Markdown
Contributor

That seems to have done the trick!

Time for and squash and a final test?

I guess you meant to post this at #22424?

@basilfx

basilfx commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

That seems to have done the trick!
Time for and squash and a final test?

I guess you meant to post this at #22424?

It was too late yesterday, and too early this morning ;-P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: build system Area: Build system Area: cpu Area: CPU/MCU ports Area: doc Area: Documentation Area: drivers Area: Device drivers Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework Area: USB Area: Universal Serial Bus CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ESP Platform: This PR/issue effects ESP-based platforms Platform: native Platform: This PR/issue effects the native platform Process: blocked by feature freeze Integration Process: The impact of this PR is too high for merging it during soft feature freeze. State: waiting for other PR State: The PR requires another PR to be merged first Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants