-
Notifications
You must be signed in to change notification settings - Fork 16
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
ISR-safe operating system functions #138
Comments
Here is one argument packed in two examples why we indeed do need ISR-safe Monitor functions for selected functions (obviously not for all of them):
So we need to look through the monitor functions and decice which ones are worth the effort. Obviously we also need to make sure that the C system works stable:
The whole VBCC part needs an extra issue. This issue is about the Monitor part. |
When we will have user/kernel mode then systhing like SYSCALL(mulu, 1) will eventually issue an interrupt and switch to kernel mode since this will be the only way to directly address physical memory addresses. Thus only the kernel (which itself is not interruptable) can access external devices and we won't have any problem with states of IO devices. :-) |
Just had a phone call: Bernd came up with a better and more elegant solution to make our operating system functions ISR-safe: We need the ability to have a "clear interrupt processing" / "enable interrupt procecssing". And then we "just" need to update all relevant Monitor functions to do a "clear interrupts" before the relevant parts (for example when accessing IO devices such as EAE) and re-enable it afterwards. Advantages:
So this issue is now all about adding this capabilities to to the Monitor and about documenting everything. It is blocked by issue #139, where the mechanism itself is developed. |
@MJoergen and @bernd-ulmann Now that #139 is done, I stumbled over one more thing: In the operating system functions such as
This costs precious performance and demands writing a lot of template code. One solution would be to have a second bit in the CSR of the interrupt controller that performs "pause/resume": When interrupts are off then pause/resume does nothing. When interrupts are on, then it pauses and then resumes. This way we only need two instructions per function that we want to make ISR-safe and we do not need to remember and restore anything. |
I like the idea of pause/resume. But that still requires two instructions in the beginning of a Monitor function:
and then another one or two instructions at the end
So that is a total of (approximately) 16 clock cycles, just for handling a potentially rare race condition. If the programmer is not using interrupts, then these clock cycles are unnecessary and a complete waste. @bernd-ulmann : You have several times mentioned adding support for user mode / kernel mode. That sounds like the way to go. Maybe we just implement that ? What I would like is a special |
Thinking of user/kernel mode I would like to suggest the following: The only way from user to kernel mode is via an interrupt (either hardware i.e. external or software - INT instruction). A system call would then be executed, as usual, by setting some parameters for the ISR in registers or the like and then issue an INT instruction. Thus we won't need any additional instructions. We would get everything else for free: Since the switch to kernel mode is done with an INT instruction, interrupts are automatically disabled when in kernel mode. Reanabling interrupts is just done by the existing RTI instruction. What do you think? :-) |
@bernd-ulmann That's exactly what I'm looking for! We can discuss this tonight, but it seems to me this is the best solution. However, there is one thing: We will want to call Monitor functions from an ISR (e.g. |
For me, user/mode kernel mode is a very big project and not just something we would do just like a small thing. Always think in terms of an overall stable project including all documentation, demos, thinking through all details, etc. Therefore I would opt for something big like that in V1.8 as V1.7 is already more than large enough. And just as a reminder for our discussion tonight: I personally love to use QNICE a lot for recreational programming: Writing a game like Q-TRIS, fiddling with something like For sure: This is solveable. But this is why I call this a large project. And of course this is how modern PCs work, but then we need to start writing smart device drivers, need to have DMA, and a lot of other things and mechanisms to still be able to have a high performance way to write recreational stuff like a game. So would then the solution be: Doing this kind of recreational programming stuff (games) in kernel mode? If yes, how would the ISR problem be solved then when the game and the ISR run in kernel mode and then the game calls a monitor function? I think we would be back in square one. Maybe for V1.7 we should opt for just stopping and restarting the interrupts using our new controller and a to be added pause/resume in the monitor function and accept the 16 clock cycles, just copied the code from Michaels #138 (comment) Start of the Monitor function:
And then another one or two instructions at the end:
|
P.S. Another solution for V1.7 could also be to make the programmers of ISRs responsible for either not using Monitor functions at all or for exactly knowhing what they are doing and saving the device's registers inside the ISR. This would save us the 16 clock cycles in general and put more load onto the shoulders of ISR programmers - which would be absolutely acceptable for me (at least for V1.7) because writing ISRs has always been a form of art... |
Solution for V1.7
|
@MJoergen Can you take over this issue and finalize it? The following tasks are left to be done and then this issue can be closed:
|
I think we still have a problem. When a regular program uses the EAE (e.g. by a multiply operation) that operation gets translated directly to accesses to the EAE, and not via a Monitor call. So I think we would need to change this, so that accesses to the EAE are guarded by the IC$BLOCK_INTERRUPTS. This should be done in |
As mentioned above the current C-compiler does not support protecting the EAE. Currently, the programmer therefore has to do this manually. I've written a proof-of-concept program in The crucial lines in the program are lines 50 and 52 in the main loop, where interrupts are temporarily blocked and unblocked, while using the EAE. Without this blocking/unblocking, the program will still generate the same numerical output, but there will be a lot of flickering on the screen, as the calculation of the background color gets corrupted. |
@MJoergen great observations. Thank you! It is cool that there exists now a test program which can be used to "visually test", if everything works.
There are actually two places where this needs to be changed:
|
@MJoergen One more thought / addition to my comment above: We might want to change to code emitter, so that C uses the monitor functions This would have the advantage, that there is exactly one place in our code-base that needs to be 100% correct and "isr-hardened": The Monitor "Operating System". Less redundancy means less error prone: As long as the monitor functions The price we would need to have to pay for that is that from then on, each 16bit multiplication in C means a subroutine call, which is less performant than today's case where direct EAE code is being emitted. On the other hand, if we would implement this thought consequently, then also the 32-bit version (We need to distinguish always two cases: The code emitter in machine.c emits code for 16-bit cases and calls specialized functions such as Your thoughts/preferences? |
I like the idea of not duplicating code, and instead have 16-bit operations call the monitor functions. I've written another test program
I looked briefly at |
Cool stuff! There is a challenge: Volker is not using GitHub and his local copy of VBCC must not have dependencies but needs to be stand alone. I think we need to brainstorm with Volker, how we can solve that and do a video call. |
Make all operating system functions that are working with hardware registers ISR-safe. For context, read #109 (comment).
Make sure that we do this in a cautious way for not wasting more ROM space than necessary.
One idea would be to have a generic "save registers" Monitor function that just starts at R8 and iterates through a given amount of registers (R9). Having such a function, the ISR versions could be as easy and memory saving as this (pseudo-code):
and then for the end-user in the ISR it would be
SYSCALL(isr_mulu, 1)
instead ofSYSCALL(mulu, 1)
.The necessity for ISR writers to use the ISR-safe versions of the OS functions is something that we should document in our programming best practices.
The text was updated successfully, but these errors were encountered: