J
James Harris
Below is a suggestion for handling - more accurately, propagating -
exceptions in C. It is intended for overall program performance though
it goes against a preference of many including me. Can anyone come up
with a faster or better way to propagate exceptions? What other ways
are there to handle exceptions in C? What do you do? (I tend to detect
exceptions where they occur by checking return values but I have never
had a good way in C to get them to propagate.)
The issue is the desire to have exception propagation using *standard*
C. I'm not talking principally about detecting exceptions but of a way
for nested functions to signal an exception and have that exception
propagate back along the call chain to a function that is set up to
handle it.
* Option 1. Use setjmp/longjmp. Not too good as, to be compatible,
they need to be used in an if or a switch statement IIRC which can be
inconvenient. Don't they also need a separate jump buffer for each
active setjmp? I have used them in the past but found them awkward.
* Option 2. Traditional exception handling. As used in other languages
this unwinds the stack of function calls looking for a handler. I
cannot think of a way to implement that in C. Furthermore, it might be
slow for two reasons: 1) the need to push and pop sufficient context
for the exception handler to recognise where a given exception should
be caught, 2) the consequent loss of sync between the stack and the
CPU's branch prediction for returns. (A return would go back to
somewhere other than where it was called from potentially impacting
the performance of the rest of the calls on the call stack.) The
latter is OK if exceptions are infrequent but is not generally
applicable.
* Option 3. The function detecting an exception creates an exception
object and sets an exception type in a thread-specific variable. Any
calling functions, after each call (or group of calls) test that
variable. If non-zero they jump to a local exception handler if there
is one or jump to a return from the current function if not. This does
involve a test and branch for each call but that is very fast (fusible
and single cycle) and it avoids the need for exception handling
context to be pushed and popped. It would also preserve the branch
prediction of calls and returns.
Unfortunately option 3 would mean use of goto. I haven't used goto in
C code for many years and don't like the idea of starting now but I
can't think of anything quicker. In C this could be
temp = func();
if (thread_excep) goto exception_handler;
x = temp;
In x86-32 this should become something like
cmp [thread_excep], 0
jne exception_handler
mov x, eax
If set up to do so the exception handler would handle the exception
itself and clear thread_excep. If not or if it decided to propagate
the exception it would return to its caller with the thread_excep word
still holding the exception value. Or it could alter thread_excep and
return.
There are subtleties but option 3 is the basic idea. Anyone know of
something better?
James
exceptions in C. It is intended for overall program performance though
it goes against a preference of many including me. Can anyone come up
with a faster or better way to propagate exceptions? What other ways
are there to handle exceptions in C? What do you do? (I tend to detect
exceptions where they occur by checking return values but I have never
had a good way in C to get them to propagate.)
The issue is the desire to have exception propagation using *standard*
C. I'm not talking principally about detecting exceptions but of a way
for nested functions to signal an exception and have that exception
propagate back along the call chain to a function that is set up to
handle it.
* Option 1. Use setjmp/longjmp. Not too good as, to be compatible,
they need to be used in an if or a switch statement IIRC which can be
inconvenient. Don't they also need a separate jump buffer for each
active setjmp? I have used them in the past but found them awkward.
* Option 2. Traditional exception handling. As used in other languages
this unwinds the stack of function calls looking for a handler. I
cannot think of a way to implement that in C. Furthermore, it might be
slow for two reasons: 1) the need to push and pop sufficient context
for the exception handler to recognise where a given exception should
be caught, 2) the consequent loss of sync between the stack and the
CPU's branch prediction for returns. (A return would go back to
somewhere other than where it was called from potentially impacting
the performance of the rest of the calls on the call stack.) The
latter is OK if exceptions are infrequent but is not generally
applicable.
* Option 3. The function detecting an exception creates an exception
object and sets an exception type in a thread-specific variable. Any
calling functions, after each call (or group of calls) test that
variable. If non-zero they jump to a local exception handler if there
is one or jump to a return from the current function if not. This does
involve a test and branch for each call but that is very fast (fusible
and single cycle) and it avoids the need for exception handling
context to be pushed and popped. It would also preserve the branch
prediction of calls and returns.
Unfortunately option 3 would mean use of goto. I haven't used goto in
C code for many years and don't like the idea of starting now but I
can't think of anything quicker. In C this could be
temp = func();
if (thread_excep) goto exception_handler;
x = temp;
In x86-32 this should become something like
cmp [thread_excep], 0
jne exception_handler
mov x, eax
If set up to do so the exception handler would handle the exception
itself and clear thread_excep. If not or if it decided to propagate
the exception it would return to its caller with the thread_excep word
still holding the exception value. Or it could alter thread_excep and
return.
There are subtleties but option 3 is the basic idea. Anyone know of
something better?
James