thewrongchristian wrote:
I also much prefer exception based error handling, and also include macro based try/throw/catch in C using setjmp/longjmp, which mostly works well. But the stack unwinding is the pain with this, as I have to install handlers to unwind any objects that need unwinding properly (like synchronisation objects), and this is cumbersome as well. I do have a facility to add "finally" blocks to try blocks, which can do this cleanup, but this is again added code that can be forgotten.
I tried this, and ended up deciding that I wanted proper C++ exceptions in kernel space.
thewrongchristian wrote:
It's just nicer to have a C++ compiler generate the extra code for you in both cases, so I'd dearly love to move to C++ and C++ exceptions, but the stumbling block being having to get this unwinding working in the kernel, and I've not tried portng the unwinding yet.
There is no reason why properly supported C++ exceptions shouldn't be used if supported, if you're careful to make your code exception safe.
Although it is absolutely possible to have C++ exceptions in your kernel and have them work properly, I concluded that this was more work than writing all the rest of the kernel.
In a nutshell (extremely simplified):
- You need to compile a stack unwinding library for your kernel that respects the kernel ABI (mcmodel, no floating point, etc.)
- That stack unwinding library is including C++ headers that have floating point numbers in them. This won't compile. You need to modify or provide new standard headers just to build the library.
- You will decide to just turn on floating point when building the library and not use the functionality in the kernel: this won't work, the compiler will start using XMM registers to move/set memory and you will end up with SSE instructions in your unwinding library.
- Add floating point (SSE) support to your kernel? Complexity will increase and performances suffer greatly. I spent two weeks on this, I concluded it was a dead end.
- You will need a pthread implementation/stubs in kernel space because the stack unwinding library is dependent on it. You can fake a lot of things here, but it is more work (I did implement enough to fake it).
- You will need a malloc/free implementation in kernel space, make sure it is thread/process-safe and doesn't use locks, because you wouldn't want to be locking each time you throw and catch exceptions. I looked into something tcmalloc, but it doesn't seem possible to easily integrate that beast into a kernel (unlike dlmalloc, which I used as a proof of concept).
- There is more I am sure, I haven't looked at this in some time.
Let's say you get all of this working. It only works with one compiler. If you want to switch to another one and/or another version, you will have to redo some of the work. There is also going to be extra work required to support other architectures.
You could instead decide to write your own unwinding library from scratch. This is even more work.
So in practice, I don't think it's worth the effort.