Re: Compiling C++ modules

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux