Korona wrote:
What does it mean for a thread to hop into a different process?
In a traditional OS processes have one or more threads. These threads are tied to their respective process.
In the OS I'm designing a process can have
zero or more threads. A thread can request the kernel to be moved into a specific process, i.e. the sending process loses a thread and the receiving process gains one.
Korona wrote:
Will it's stack be copied? Mapped into the other process? What if there is another thread that shares the same stack address?
A thread will not have any stack when it is moved. Instead, it allocates a new one which can be as small or as big as it needs to be.
Korona wrote:
What if the thread wants to take data back to the original process? Where will that data be stored?
Before hopping, the thread specifies either a range of pages to be shared/moved or an address with a small amount of data to be copied. After hopping, it either maps the pages into the process' address space or copies the data to wherever.
Octocontrabass wrote:
You can have the same thing with a more typical scheduler by spawning a new server thread in response to each client request. Of course, you won't get the other advantages that way.
I am considering this approach, but the memory overhead can add up quickly if there are many pending requests.
Octocontrabass wrote:
Even if the scheduler doesn't see blocked threads, you still need to store the entire thread's context somewhere, so I'm not sure you're lowering memory usage.
I expect memory usage to be lower overall since there is likely stack space that is already allocated anyways & the user knows which registers actually need to be preserved (e.g. the contents of temporary registers may be safely discarded).
thewrongchristian wrote:
Real-time doesn't really apply to IPC. When talking about real time, it's more in the context of responding to events like hardware interrupts. In the case of hard real time, within hard bounded time.
Audio servers benefit from real-time scheduling since audio latency is very noticeable.
thewrongchristian wrote:
Your single kernel thread per core doesn't make that any easier.
I don't intend to have a single kernel thread per core. Instead, kernel threads are treated as regular threads except that they operate on kernel memory (& they can become user threads when necessary).
thewrongchristian wrote:
Should be simple enough. Switching to a user level context is simple.
Indeed. I raised the issue because in a previous design I tried to do state restoration entirely in userspace which could be complex since the process has to check it isn't being spoofed (e.g. a malicious thread could hop into a client pretending to be the response of another process).
thewrongchristian wrote:
A thread that is not running, especially if it has no stack, will not use any resources other than what small amount of memory is required to maintain its state.
On 64-bit systems with 32 registers a thread uses at least 256 bytes of memory. While it isn't much by itself, it can add up quickly if there are many blocked or sleeping threads. I do also intend to have many "threads" "running" at the same time since I believe it is the easiest to scale across many cores.
thewrongchristian wrote:
This is the model used by, for example, protothreads, which is very high performing in low memory situations, but is inherently difficult to use as the complexity of the task the thread has to achieve goes up (you're basically restricted to a single function per thread).
I'll give it a read. Thanks!
____________
A major reason why I'm considering this approach is so that processes can naturally take advantage of all cores on a system. I could of course create as many threads per process as there are cores, but this may result in significant overhead if there are many cores and many processes. This overhead is avoided by creating or moving a thread on demand.