Messages in this thread | | | Date | Tue, 25 Apr 2006 20:53:01 +0300 | From | Avi Kivity <> | Subject | Re: 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/
| |