But the way the immisability layer is achieved is through relipsy and redox archi.
So first, our C library, relipsy, and again, for what ironically, it's written almost entirely
in rust, even many of the header files or order generated using C bind gen from rust declarations.
So the only real C code in relipsy is essentially what bossy requires in the form of same
macros and other other special C specific definitions.
And it's been rustifying over time, reducing unsafe, so for example, howling C strings can
be done safely encoded using the rust type system.
There are both a Linux and a redox back end that Linux back end is in particularly interesting
for this talk.
But the redox back end is what implements the large parts that constitute our policy support.
So redox archi is currently on top of a simpler kernel APIs for example, creating your
either spaces sending pages between outer spaces, switching the current outer space.
So one, and importantly also the quiet large at this point signal handling subsystem.
So what we're trying to achieve with this signal subsystem is to essentially support the
user space analog of hardware interrupts.
So they're really similar.
There are roughly 64 signals, even though that's implementation specific.
There is synchronous, they can interrupt execution at any time when they're not masked
or ignored, and they can also interrupt two skulls that would otherwise lock.
But the way our current redox RTA approach is implemented.
This policy is quite huge problem when signals can occur, because if for example store
this current working directory state, which needs to be accessed every time you open something.
Since this state is a global variable, and since multi-threading is supported, this needs
to be synchronized.
And although that doesn't necessarily have to be implemented using a mutex, impractice
that will always be sort of required.
And the problem is the functions like open they're async safe, which means they can be called
re-entrously.
So this policy is a huge problem when you need synchronization.
Now before all of this functionality was moved to use space, when it's still recited in the
kernel, this would have been a trivial problem, because interrupts are almost always disabled,
at least on the redox microphone.
And doing that manually would have been more than 10 times cheaper, give or take.
So we really need to be able to quickly disable signals for short critical sections.
So that brings us to the question, what if we could bypass the fiscal overhead entirely
and say you've shared memory instead?
And that's exactly what this protocol does.
So it keeps the cost of sync prox mask low, and even bypasses the kernel entirely, at least
in terms of switching to kernel mode.
And it keeps all of this signal configuration state, except the pointers the kernel uses
to access the same state.
And it also provides a basic IPC cancellation primitive.
So essentially all of the configuration is done using shared memory, which in use is based
in kernel space.
Now this allows the kernel implementation to be really simple, rather than having to say
a restore registers inside the user address space that's going to be signal.
The only thing the kernel needs to do is just remember what the instruction pointer was,
set the new instruction pointer to the signal trampoline, as well as save one extra scratch register
so the assembly in the signal that can actually do anything useful.
So it makes the kernel really simple, but it does make users' base quite a lot more complicated,
because now it essentially needs to implement an analogical ended with the per thread allow mask.
So each thread can disable enable signals and have signals sent to that thread specifically
or to the entire process.
Of course there are also some ad hoc protocol behaviors for things like stop signals
and real-time signals that have special requirements.
But to explain this, well to depict this, the way this works, again you have these per thread
areas, generally in the PCB, as well as the per process area, which is just a global variable.
The depending set here shows in logical or between the per process and per thread sets
and the allow shows the per thread allows it.
Now the logical end of these will give the set of pending unlock signals from which
the passics requires that for real-time signals, at least that the lower signal be picked.
And then there is also this additional bit that allows not
affecting the way signals can interrupt things, et cetera, between threads,
but just on the same thread whether the kernel will jump a user base.
So when this mask bit is clear and you take the signal, it will be possible to deliver that signal.
So for this to work, the protocol could, in theory, have been implemented as multi-producer
multi-consumer, but that would have made the protocol way too complex to handle, I think.
So the way it works is essentially, you need mutual exclusion for sending signals.
Only the kernel is currently allowed to do this later, the process manager will do it instead.
When you kill a single thread, you set the pending bit for the corresponding signal for that thread.
You then check as a separate atomic cooperation, whether that's seeing was allowed.
And if both conditions are upheld, you will notify that thread and then wait for the signal
trampoline later to clear the bit for that thread. For processes it's a bit more complex.
You set the process level pending, you then walk through each individual thread,
looking for one, that signal is unlocked. Then once you found one, you unblock it and later wait
for it to, at some point, clear the signal bit later. This can, in theory, result in
spears signals, but this shouldn't be a problem considering that's, in my opinion, misuse of the API.
For, for, for introduction to work, while there are IPC circles ongoing, this of course needs
to support some form of cancellation. First, to explain the basic IPC model on redox,
the way it works is, essentially, if you have, for example, read from the socket, you'd call
a suspreed to. This is synchronous for the client, but asynchronous for the server. So,
you'll wait for the context, for the scheduler to context which, to the server.
And, which will, for cancellation to work, this essentially happens asynchronous as well.
It just sends an, a cancellation request, and this is for IO state to not be broken,
say if there were bytes that were just about to arrive, and then there was a signal. Of course,
those bytes should arrive before the inter, or sent, signal can force cancel however.
So, yeah, in general, this signal's implementation has allowed for increased
POSIX coverage, both in terms of raw new implement APIs, and the, and the
versatility in technical terms of the, of the underlying signals implementation.
The standard has, in general, been quite easy to work with, with a few exceptions, and that's
me, the fact that POSIX has derived from Unix, which has all of these, like ad hoc exceptions,
like what happens if a stop signal is interrupted by a continuation signal, and so on,
that perhaps wouldn't have been there, if this protocol had been designed for microcom, microcom
regionally. There's also, there's also a bigness, say, what happens if a real time signal was sent
at the standard way, or vice versa. The implementation will lead some further testing, since it's,
well, since, since it essentially requires separate sort of inter-pandlers for each arch,
but the protocol should be pre-reboast. Additionally, the process manager will take over the
Colonel's role as the, as responsible for sending signals. But in general, with dynamic, with
dynamic linking progress, having been made a lot recently, this will greatly improve the mechanisms
for further user-pasification, now that the signal performance problem has, in large part, been
overcome by this new memory interface. And this way, it will potentially be possible to
use your pacify even further deeper parts of POSIX, such as the file table allocation,
and so on, every time you access a file descriptor. So yeah, I hope the user-specification can
continue. That's the end of my talk.
Thank you very much for this great talk. We have two minutes for questions in the back.
Sorry, can you repeat the question for you?
Oh, right. So, so, so your question was if if the implementation uses,
like supports real times from Q, rather than be behavior, that the same signal occurs
at most ones before is delivered, which is the case for the lower 32 bits.