Sorry guys, I may be getting off topic, but any hints/help or
any pointer to any link would do.
I was looking at some code that is written
for an SMP system. My problem is again related to the
reordering of instructions.
some_function(struct some_struct *strptr)
{
take_spin_lock(&global_variable); /* line 1 */
strptr->some_member = some_value; /* line 2 */
some_other_global_var++; /* line 3 */
release_spin_lock(&global_variable); /* line 4 */
}
In the code, neither "global_variable" nor "strptr" and
"some_other_global_var" are volatile.
Also, any member of "strptr" and "some_other_global_var"
should only be changed after holding the spin_lock.
Now, my question is that, is it possible that compiler
may reorder these instructions so that line 2 and line 3 are
executed before line 1 ? Note: from compiler point of view the
operations are independednt.
In that case, taking spin lock is of no use and the code
may not work as desired.
From C's point of view, the undesired reorderings are
permitted if and only if nothing in take_spin_lock() and/or
release_spin_lock() affects or is affected by or even "sees"
strptr->some_member and some_other_global_var.
From the compiler's point of view, it is very difficult
to know what tsl() and rsl() might do, and hence to "prove"
that they operate independently of s->sm and sogv. This
usually means that the compiler will not reorder operations
across function calls if they involve potentially non-local
variables. ("Potentially non-local" isn't a phrase you'll
find in the Standard, but I hope it makes sense anyhow.) The
conservative approach is pretty much obligatory when calling
an external function whose innards are not "visible."
From the point of view of other standards that apply to
parallel programs, certain functions carry special guarantees
and it is the compiler's duty not to violate them. For example,
the POSIX threading standard requires pthread_mutex_lock() to
behave as everything initiated before the call completes before
the function returns, and that nothing initiated after the
return begins before the call. (I'm speaking very loosely here;
go to comp.programming.threads if you want more detail.) POSIX
doesn't say how the implementation achieves this effect, just
that an implementation that fails to achieve it is broken.
It may be that take_spin_lock() and release_spin_lock() are
covered by similar guarantees on the system where they're being
used, or it may simply be that whoever invented them relied on
the compiler being "conservative" in the sense mentioned above.
In all other functions, I am finding the similar issues but
nowhere any variable is declared to be volatile. Also,
I believe the optimization is not switched off.
On c.p.t. it's pretty much a FAQ that `volatile' is neither
necessary nor sufficient for thread synchronization. (It is
still necessary for some other purposes, though. For example,
you need it for the situation in your original question, which
does not seem related the question you're asking now.)
I also believe that there is no bug in this code, but
dont know how it works ?
Can anybody, please tell me what is that I am missing ?
The code relies on guarantees that are not part of the C
language, that's all. It may come as a shock to some, but the
C Standard is not the only Standard in the universe, and the
universe holds many useful things not found in Standards.