kern/99979: Get Ready for Kernel Module in C++

Sergey Babkin babkin at verizon.net
Thu Jul 13 12:14:51 UTC 2006


>From: "Kamal R. Prasad" <kamalp at acm.org>

>Im sorry I didn't understand you. setjmp() stores a few register contents
>[notably ip] in a jmpbuf -which are restored after a longjmp(). How is the
>try/catch mechanism more efficient than a setjmp()/longjmp() in terms of
>space/time complexity?

try/catch stores less. Besides, longjmp() is nothing like
try/catch. The whole point of try/catch is that as the
stack gets unwound, all the auto-class objects get
properly destroyed. When you do longjmp, you just move
the instruction pointer and stack pointer, and if
any of the objects on the stack contained pointers
to any dynamically allocated memory, it gets lost.
If there were any file descriptors opened along the way,
they are left open too. If there were any locks held,
they stay locked. To prevent this loss with longjmp, you 
have to track all these objects manually.

Note that even with try/catch it's a Real Bad Idea to throw
exceptions from constructors and destructors, as this
causes complications.

-SB

>On 7/12/06, Joerg Sonnenberger <joerg at britannica.bec.de> wrote:
>>
>> On Wed, Jul 12, 2006 at 06:33:09PM +0530, Kamal R. Prasad wrote:
>> > On 7/12/06, Joerg Sonnenberger <joerg at britannica.bec.de> wrote:
>> >
>> > >On Tue, Jul 11, 2006 at 11:37:52PM +0200, Attilio Rao wrote:
>> > >> Even if I have no proof-of-concepts (so maybe somebody can show that
>> > >> this is not fair), if we have setjmp/longjmp in the kernel we can
>> have
>> > >> a correct exception handling mechanism without not great problems.
>> > >
>> > >ROFL. Sorry, but using setjmp/longjmp is one of the worst possible
>> > >implementation of exceptions since it is very expensive for the hot
>> > >path, where you don't expect exceptions. They are called "exception"
>> for
>> > >a reason.
>> >
>> >
>> > so how is exception handling in C++ more efficient than
>> setjmp()/longjmp()
>> > -in either paths?
>>
>> The common implementations are based on two assumptions:
>> - try {} is used often through out the tree and nested
>> - exceptions are raised seldomly.
>> This means that the desire to catch an exception should be cheap and the
>> implementation optimised for that.
>>
>> What happens is that the compiler creates a table which allows automatic
>> stack unwinding and matching of the instruction pointers. The former is
>> necessary to handle frame pointer vs. frame pointer-less stack frames,
>> the latter is used to determine where an exception should be cought.
>>
>> Consider:
>> void bar()
>> {
>>        throw "foo";
>> }
>>
>> void foo()
>> {
>>        try {
>>                bar();
>>        } catch(...) {
>>                cerr << "error";
>>        }
>> }
>>
>> (don't try that, I haven't written C++ for ages)
>>
>> The compiler creates:
>> - an entry for the range of bar to annotate that it doesn't have use a
>> frame pointer
>> - an entry for foo, with the same annotation
>> - the address when bar is called in foo (or the address directly
>> following) to annotate that it should jump to catch, when an exception
>> is raised.
>>
>> When an exception is raised, it looks at the current instruction pointer
>> and begins unwinding the stack until a catch is found. This can be
>> relatively cheap compared to longjmp, since the register content does
>> not have to be restored. It does not add any slowdown, as long as
>> exceptions are not raised.
>>
>> Joerg
>> _______________________________________________
>> freebsd-hackers at freebsd.org mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"
>>
>_______________________________________________
>freebsd-hackers at freebsd.org mailing list
>http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"



More information about the freebsd-hackers mailing list