DP thread - start early
This is the beginning of the user-space SOF work. To enable DP threads to run in user-space we want to start them early to also call all callbacks from their modules in the thread context. This PR does that - starts the thread early to prepare for the context conversion
We need to start the DP thread earlier, before creating module_adapter, to be able to call the module entry point in the user context.
We need to start the DP thread earlier, before creating
module_adapter, to be able to call the module entry point in the user context.
the freeing is done later in a newer version of this patch, as for the entry - maybe we can make that optional, at least with LLEXT we should be able to easily enough get rid of it and just get ops directly from an ELF section
one general comment
Using DP thread to other tasks but data processing is a bit risky - may lead to starvation
- DP priority is low, lower than LL
- IPC thread should be "task with budget", preemptible when the primary task - audio processing - is at risk of underrun
- DP may process long, very long - even 100ms. That is was designed for. IPC would have to wait (100ms may occur if i.e. there are couple of DP threads, one in 1ms period, second in 100ms. Even it "100ms period" processing can finish. lets say in 10ms, it will be preempted to let "1ms' DP thread finish in its deadline, "100ms" task may start at 0ms and finish at 99.9ms and it is OK)
- increasing priority won't help if the processing as above is in progress, thread is busy and can't be interrupted
- situation will become more complicated with DP to DP connection and deadline chain calculation finally introduced (PR is almost ready)
- and the worst - all of the above will be invisible and not detectable when CPU is not heavily loaded. IT will, however, limit whole system performance and cause IPC timeouts or glitches at unexpected moments.
Theory of EDF scheduling says it may utilize CPU in 100%, lets not spoil it.
I would strongly recommend using a separate thread for IPC for DP - AFAIK a thread may be switched from one user space to another, so a single worker, properly switched from one user space to another - will be enough and won;t consume too much resources. It will save a lot of problems
I would strongly recommend using a separate thread for IPC for DP - AFAIK a thread may be switched from one user space to another, so a single worker, properly switched from one user space to another - will be enough and won;t consume too much resources. It will save a lot of problems
@marcinszkudlinski we don't have 100ms long DP modules so far, looks like ATM we aren't expecting any that could run longer than 20ms. If we ever get such slow modules, then yes, then we can consider adding support for a separate thread.
why not now? Less complicated that future refactoring. Are there advantages to re-use of DP thread vs 1 common thread - except for one less stack in RAM?
why not now? Less complicated that future refactoring. Are there advantages to re-use of DP thread vs 1 common thread - except for one less stack in RAM?
@marcinszkudlinski Are we sure that we'll ever need that? I'd prefer to first enable the simpler version if we don't know if we ever need the more complex one. Besides I personally don't find the concept of switching memory domains particularly elegant. And the alternative would be at least an additional thread per "trust circle" (vendor / module interface), which is then not one but potentially several such proxy threads
With this state SRC can be run in DP mode and all its hooks will run on the SRC DP thread, no SRC code will execute in "base firmware" context. In fact that isn't quite right when SRC is built as an LLEXT module - then a one-line entry function will be called by the base firmware directly. Fixing that in the next step.
why not now? Less complicated that future refactoring. Are there advantages to re-use of DP thread vs 1 common thread - except for one less stack in RAM?
@marcinszkudlinski Are we sure that we'll ever need that? I'd prefer to first enable the simpler version if we don't know if we ever need the more complex one. Besides I personally don't find the concept of switching memory domains particularly elegant. And the alternative would be at least an additional thread per "trust circle" (vendor / module interface), which is then not one but potentially several such proxy threads
I think we are fine today (as the 1st step) with the single thread (since we dont have long period DP configs today), but adding the IPC thread can come next as a topology flag i.e. DP module configured for long period, pls fork a second thread for module IPC.
I think we also need to look at IPC serialization too, it seems we can have improvements to support multiple messages per doorbell ring and more concurrency. Wont help us today though, but it is possible as future improvements.
@lyakh
I'd prefer to first enable the simpler version.
One separate worker will certainly be simpler.
the alternative would be at least an additional thread per "trust circle" (vendor / module interface)
Since we only have one IPC thread, one worker will suffice. Having multiple workers and the concept of "trust circle" is pointless.
@lyakh
I'd prefer to first enable the simpler version.
One separate worker will certainly be simpler.
the alternative would be at least an additional thread per "trust circle" (vendor / module interface)
Since we only have one IPC thread, one worker will suffice. Having multiple workers and the concept of "trust circle" is pointless.
@softwarecki Modules shouldn't be allowed to access each other's memory, so you cannot run code of module A while being allowed to access memory of module B. So if you have a single user-space IPC helper thread, you'd need to switch its permissions / domain every time you need it to execute on behalf of a different module. This supposedly means reconfiguring the MMU context / reloading page tables.