-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Fix shell threadless support #93184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix shell threadless support #93184
Conversation
a5749f7
to
5d63c28
Compare
shell is not listed as something we wanted working/supported with no threads. https://docs.zephyrproject.org/latest/kernel/services/threads/nothread.html |
Time to change that then :) Logging is not listed here either, but that works single threaded as well |
well, no. That page https://docs.zephyrproject.org/latest/kernel/services/threads/nothread.html exists for a reason. This is to limit this non-sense of making everything in zephyr single threaded and littering the code with senseless ifdefs. The project has decided and agreed long time ago to contain this and not allow single thread support in more than what is listed there. Maybe it is time to enable threading in the bootloader, because the reasoning was always footprint, but then, why are you enabling shell in a bootloader? (or logging or whatever). |
Shell in a bootloader can be useful, and takes up waay less resources if it works with single threading. Furthermore, the change for now just allows either no thread (threadless) or multithreaded (one thread for each shell). One thread for each shell is really expensive, adding flexibility to allow for a shell backend to be run from a work queue for example can dramatically optimize systems with multiple shells (if the user chooses to, it should be an option). The end goal is to separate the shell instance from the thread instance, similar to what we recently did for work queues, where any thread can "take over" / "execute" any shell instance, for example, reusing the main thread to run a shell would be efficient no? |
The shell subsystem currently uses k_poll for signalling. However, k_poll is only used for simple event signals, results are not used. Replacing the k_poll with k_event greatly simplifies the code, and saves 4 struct k_poll_signal and 4 struct k_poll_event (one of which was entirely unused) while costing a single struct k_event, for every shell instance. It also allows us to not select POLL, as we are using the simpler EVENTS instead. A quick test build of the shell test suite on an nrf54l15 produces the following build info: using EVENTS: FLASH: 71592 B 1428 KB 4.90% RAM: 9872 B 188 KB 5.13% IDT_LIST: 0 GB 32 KB 0.00% using POLL FLASH: 75524 B 1428 KB 5.16% RAM: 11224 B 188 KB 5.83% IDT_LIST: 0 GB 32 KB 0.00% Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
The mutex is being used as a simple binary semaphore. It is not recursed so we don't need to track thread ownership nor lock count. Exchange the mutex for a binary semaphore to save resources and speed up shell. Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existential argument about whether/how to support MULTITHREADING=n notwithstanding, this looks pretty reasonable to me.
One tidiness complaint is that this is now filled with "#ifdef CONFIG_MULTITHREADING
around common idioms like the lock and event handling that you might clean up with local function like shell_un/lock()
, shell_event_signal()
etc... where they can evaluate to noops when not needed.
great minds something something: 954f8b6 I'm doing quite a bit of cleanup so the ifdefs should go to near extinction :) This PR for now is just a draft POC. On top of this, I am looking into making the struct k_sem itself adapt to single threading (thread + isr) where it gets converted to a while loop and an atomic :), this way drivers using k_sem for signalling from ISRs will still "work", as in behave similarly from the outside, but that is a future thing |
The shell at some point supported CONFIG_MULTITHREADING=n but this has not been maintained. Adjust the shell to support threadless operation similar to how logging works with no logging thread. With these adjustments, building with CONFIG_SHELL_MINIMAL and CONFIG_MULTITHREADING=n, shells can now be used like logging by calling shell_process() with non-polling backends, like async or irq driven UART based backends. Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
Introduce threadless shell sample which shows how to build and use shells in threadless (single threaded) applications. Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
Extend nothread docs to list the shell subsystem using the serial shell backend as expected to work with CONFIG_MULTITHREADING=n Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
2351d03
to
e96fda6
Compare
rebased to include the |
|
The shell at some point supported
CONFIG_MULTITHREADING=n
, but this has not been maintained. This PR fixes that build option, and adds a sample to show how to use it, and ensure it is not broken again :)This PR is based top of the k_poll to k_event refactor, not really needed to fix the shell but I believe it will go in so this could save a bit of rebasing later :)
Tested on nrf54l15dk/nrf54l15/cpuapp (nordic), b_u585i_iot02a (stm) and frdm_ke15z (nxp)