Hello Alexander,
So, you want to keep FreeBSD structure and related functions by replacement of the code inside old infrastructure to direct switch ones? See some doubts below (except some potential problems related to «native» FreeBSD infrastructure, as mentioned in previous letter).
Note: Under "worse performance" I mean that current FreeBSD borrowed code assume context switch to kernel and back for every get/set context. In theory, we can call native context-switching functions from underlaying kernel (while it will be unique for every kernel, no common code). I don’t like this approach as non-portable.
That is true - normally you do not have access to the kernel directly on Genode (I am not even sure if all kernels supported by Genode provide such functionality) and that will not change, especially for entirely libc-based components.
the problem that this family together with headers and ucontext structure is a part of general libc. how I can mask its usage, e.g. in configure scripts?
That is indeed a problem and one of the reasons why I already mentioned that using configure for building *libraries* for Genode is not the way to go. For the time being the manual effort of writing library .mk files to bring a library to Genode is the preferred way.
In doing so the library is better integrated into Genode's build-system (amongst others, this also eases cross compilation), you gain more insight into the target you are currently porting as you are required to check the compilation units as well as the used compiler flags. Generally speaking you are more in control of the compilation process and do not rely on the original “black-box”.
In the case of GCC's libgo the overhead of this manual approach should not be so high because I would imagine it would be updated together with the tool-chain, which is around every 2 years (I do not how intertwined the library is with the compiler).
That being said, with better tooling in place it is quite possible to reuse the existing build tools in the future.
Due to specific of Genode we have another potential problem - we can’t use standard malloc() for stack allocation because stack should be from specific memory area to allow context switch, so, external packages compatibility will be limited anyhow.
I would argue that if go-packages operate on a level where they need to know where or how the stack is allocated you properly want a Genode-specific backend anyway. Or is that an implementation detail that leaks through the standard library?
By the way, what is a reason for this? it is relatively fast and easy to make a separation between «main» and «other» threads using, e.g. registry...
And, last but not least - setcontex/getcontext should store and restore signal context (including signal handlers) which is not that clear for me in Genode. Currently is is limited, and where it should go later? how we can store/restore state of signals for current thread?
That is a good question where I do not have an answer. In general the signal handling in our libc is minimal and we rely on user-code to call an preemtion point (“system-call”, I/O) to deliver signals, i.e., there is no preemption through signals.
So, returning back. I can try to put everything in *context with uniq name (replace original files and function names) into world repo, and force libgo to call these function. Anyway, any other software porting will require manual efforts mainly because of old/rest of headers from libc.
Also to use functions I need C interface for allocate_seconday_stack() which should be somewhere inside (I choose libc dummies.cchttp://dummies.cchttp://dummies.cc file) Question: may be better other place? e.g. inline C interface function as a part of e.g. thread.h? Any recommendations are welcome!
I understand your point, so, another question is: how I can continue if patch can’t be stored inside genode core? it can’t be significantly smaller (4 functions/files to be add at least)...
Everything else for golang support I will have in world, this is the only part of core (may be together with extended anonymous mmap support).
Please see my branch [1] where I have changed your code in a way that the whole mcontext implementation is now part of a static library “mcontext-support” that is linked against your mcontext test component. Hopefully I did not break anything in the process; the test seems to be fine. It also contains the 'allocate_seconday_stack' implementation.
[1] https://github.com/cnuke/genode/commits/mcontext-2021-03-23
The context API is still stubbed in the libc and you will see the dummy calls at run-time but you can override them by providing your own implementation. Naturally the implementation should use the ucontext_t data structure from the libc to prevent any memory layout issues. If that is possible to uphold you could as well bring the glibc implementation back.
(I removed the available makecontext implementation because it seems to be merely a left-over that is not required. Stubbing it as well feels more in line. I moved the implementation into the support library which is why it depends on libc to get access to the header files because I omitted making the compilation unit standalone.)
So in case of go, the libgo library should be linked against such an support library, that - as it uses the Genode API - needs to be linked against the Genode base library. If that is not possible, presumeably because adding additional libraries to libgo's build-system is cumbersum, linking your go component against the library should do the trick.
It goes without saying that this approach only works if you are fine with linking against the base library but I think for the time being that is workable solution. It removes extending the libc from your critical path and gives us time to decide how to deal with it properly.
Please let me know if you share the assessment or if I am still missing something obvious.
Regards Josef