lkml.org 
[lkml]   [2006]   [Apr]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: Compiling C++ modules
Dmitry Torokhov wrote:
>>>>>
>>>> No, it's optimized out. gcc notices that &lock doesn't change and that
>>>> 'l' never escapes the function.
>>>>
>>>>
>>> "l" that propects critical section gets thrown away???
>>>
>> Calm down, the storage for 'l' is thrown away, but its effects remain.
>>
>
> Would you mind explaining implemenation details a little bit?
>
(I don't know how familiar you are with C++ so I'm explaining it from
the basics, apologies if I'm repeating things you know)

Very often one needs to acquire a resource, do something with it, and
then free the resource. Here, "resource" can mean a file descriptor, a
reference into a reference counted object, or, in our case, a spinlock.
And we want "free" to mean "free no matter what", e.g. on a normal path
or an exception path.

In C++, you code it as a guard object:

struct spinlock_guard {
spinlock_guard(spinlock_t *lock) { sl = lock; spin_lock(sl); }
~spinlock_guard() { spin_unlock(sl); }

spinlock_t *sl;
};

(this would be coded differently, trying to keep it C-like)

To use it, create a spinlock_guard object that goes into scope before
you use the data you want to protect:

spinlock_t some_lock.;

void f()
{
blah();
spinlock_guard guard(&some_lock);
__f(); /* do nonatomic stuff */
if (__g())
return;
__h()
}

C++ treats this as if you've written:

spinlock_t some_lock;

void f()
{
spinlock_guard guard;

blah();
guard.sl = &some_lock;
spin_lock(guard.sl);
__f();
if (__g())
goto out;
__h();
out:
spin_unlock(guard.sl);
}

Additionally, C++ guarantees that if an exception is thrown after
spin_lock() is called, then the spin_unlock() will also be called.
That's an interesting mechanism by itself.

Now, the optimizer sees that guard.sl is a constant expression
(&some_lock), and that guard.sl's address is not passed to any function,
so it eliminates the variable entirely, leaving us with


spinlock_t some_lock;

void f()
{
blah();
spin_lock(&some_lock);
__f();
if (__g())
goto out;
__h();
out:
spin_unlock(&some_lock);
}

(the original C++ compiler actually worked by writing out the C code and
letting the C compiler compile it; nowadays both compilers use the same
intermediate representation, optimizer, and code generator).

--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2006-04-25 19:56    [W:6.240 / U:0.132 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site