473,378 Members | 1,309 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

instruction re-ordering

Hello everybody!

Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();

Thanks in advance!
Loic.

Jan 12 '07 #1
15 1812
loic-...@gmx.net wrote:
Hello everybody!

Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();
It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.

Jan 12 '07 #2
Harald van Dijk a écrit :
loic-...@gmx.net wrote:
>>Hello everybody!

Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();


It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.
That could be done only if

call_once(int* restrict done, void(*routine)(void))

If the "restrict" keywords would have been used yes, you could have done it.
Jan 12 '07 #3
jacob navia wrote:
Harald van Dijk a écrit :
loic-...@gmx.net wrote:
>Hello everybody!

Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();

It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.

That could be done only if

call_once(int* restrict done, void(*routine)(void))

If the "restrict" keywords would have been used yes, you could have done it.
It can also be done if the compiler chooses to inline a specific call
to call_once.

Jan 12 '07 #4
"Harald van D?k" <tr*****@gmail.comwrote in message
news:11*********************@38g2000cwa.googlegrou ps.com...
loic-...@gmx.net wrote:
>Hello everybody!

Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();

It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.
Your observation now has me shaking in my boots!

You are scaring me!

We all know that the "volatile" keyword tells the compiler that it can't
reduce this:

<BEGIN>
volatile int x;
int y, z;

while (y = x) /* Notice this is assignment, not comparision. */
{
z += y;
}
<END>

to this:

<BEGIN>
volatile int x;
int y;
int z;

y = x;

if (y != 0)
{
while (TRUE)
{
z += y;
}
}
<END>

But your comment scares me because "volatile" variables (in microcontroller
work, often hardware control registers) often are linked because groups of
them collectively control [typically] hardware peripherals. These are not
simple assignments or tests, i.e.

CR1 = 0;
CR2 = 0;

may have a very different effect than:

CR2 = 0;
CR1 = 0;

So, in the OP's example, if routine() modifies a hardware control register
and *done is one also, REORDERING THE STATEMENTS WOULD POTENTIALLY HAVE AN
EFFECT, EVEN THOUGH THE COMPILER COULD NOT DETERMINE ANY "INTERACTION"
BETWEEN THE TWO REGISTERS.

I need to look up "volatile" in the standard. This is scaring me.
Jan 13 '07 #5

On Fri, 12 Jan 2007, David T. Ashley wrote:
"Harald van D?k" <tr*****@gmail.comwrote in message...
>loic-...@gmx.net wrote:
>>>
Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();

It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.

Your observation now has me shaking in my boots!

You are scaring me!

We all know that the "volatile" keyword [...]
Before turning on the sarcasm full force, be sure you proofread
both the original post and your response. There was no 'volatile'
anywhere in the OP. Harald's interpretation is 100% correct.

[...]
So, in the OP's example, if routine() modifies a hardware control register
and *done is one also, REORDERING THE STATEMENTS WOULD POTENTIALLY HAVE AN
EFFECT, EVEN THOUGH THE COMPILER COULD NOT DETERMINE ANY "INTERACTION"
BETWEEN THE TWO REGISTERS.
If *done is a hardware control register, then the user probably
made a mistake in not declaring it 'volatile'. But that's irrelevant;
you don't need to invoke weird 'volatile' objects in order to come
up with a scenario where reordering the statements would be invalid.

HTH,
-Arthur
Jan 13 '07 #6
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
news:Pi***********************************@unix32. andrew.cmu.edu...
>
If *done is a hardware control register, then the user probably
made a mistake in not declaring it 'volatile'. But that's irrelevant;
you don't need to invoke weird 'volatile' objects in order to come
up with a scenario where reordering the statements would be invalid.
You genuinely did not understand the technical nuances of my post.

The issue is that even if you declare a data item "volatile", there is the
notion of effectively "co-volatile", where volatile data items are not
independent.

The issue isn't whether one can come up with a scenario where reordering is
invalid ... the issue is whether one can come up with a scenario where
reordering is invalid and the compiler can't detect it.
Jan 13 '07 #7
David T. Ashley wrote:
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
news:Pi***********************************@unix32. andrew.cmu.edu...

If *done is a hardware control register, then the user probably
made a mistake in not declaring it 'volatile'. But that's irrelevant;
you don't need to invoke weird 'volatile' objects in order to come
up with a scenario where reordering the statements would be invalid.

You genuinely did not understand the technical nuances of my post.

The issue is that even if you declare a data item "volatile", there is the
notion of effectively "co-volatile", where volatile data items are not
independent.
It's the other way around. Compilers are not allowed to assume volatile
data accesses are independent.

Jan 13 '07 #8
"Harald van D?k" <tr*****@gmail.comwrote in message
news:11**********************@51g2000cwl.googlegro ups.com...
David T. Ashley wrote:
>"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
news:Pi***********************************@unix32 .andrew.cmu.edu...
>
If *done is a hardware control register, then the user probably
made a mistake in not declaring it 'volatile'. But that's irrelevant;
you don't need to invoke weird 'volatile' objects in order to come
up with a scenario where reordering the statements would be invalid.

You genuinely did not understand the technical nuances of my post.

The issue is that even if you declare a data item "volatile", there is
the
notion of effectively "co-volatile", where volatile data items are not
independent.

It's the other way around. Compilers are not allowed to assume volatile
data accesses are independent.
OK, fair enough. But is there anything in the standard that says the
compiler can't reorder this:

volatile int x,y;
x = 0;
y = 1;

to

volatile int x,y;
y = 1;
x = 0;

Now, the reasons for reordering could be subtle. For example, "1" may
already be in a CPU register and it is more efficient to do the "1"
assignment before the "0" assignment.

Is this prohibited?

Dave.
Jan 13 '07 #9
David T. Ashley wrote:
"Harald van D?k" <tr*****@gmail.comwrote in message
news:11**********************@51g2000cwl.googlegro ups.com...
David T. Ashley wrote:
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
news:Pi***********************************@unix32. andrew.cmu.edu...

If *done is a hardware control register, then the user probably
made a mistake in not declaring it 'volatile'. But that's irrelevant;
you don't need to invoke weird 'volatile' objects in order to come
up with a scenario where reordering the statements would be invalid.

You genuinely did not understand the technical nuances of my post.

The issue is that even if you declare a data item "volatile", there is
the
notion of effectively "co-volatile", where volatile data items are not
independent.
It's the other way around. Compilers are not allowed to assume volatile
data accesses are independent.

OK, fair enough. But is there anything in the standard that says the
compiler can't reorder this:

volatile int x,y;
x = 0;
y = 1;

to

volatile int x,y;
y = 1;
x = 0;
That's a special case, since the compiler might be able to know that
it's impossible for x and y to be stored in memory where access order
matters. I'll pretend you used "extern volatile int x,y;" instead.
Then, since the compiler can only perform that optimisation if the
accesses are independent, and the accesses can't be proven to be
independent, that optimisation is not valid.

Jan 13 '07 #10
"David T. Ashley" <dt*@e3ft.comwrites:
[...]
OK, fair enough. But is there anything in the standard that says the
compiler can't reorder this:

volatile int x,y;
x = 0;
y = 1;

to

volatile int x,y;
y = 1;
x = 0;
[...]

Yes. C99 6.7.3p6 says:

An object that has volatile-qualified type may be modified in ways
unknown to the implementation or have other unknown side
effects. Therefore any expression referring to such an object
shall be evaluated strictly according to the rules of the abstract
machine, as described in 5.1.2.3. Furthermore, at every sequence
point the value last stored in the object shall agree with that
prescribed by the abstract machine, except as modified by the
unknown factors mentioned previously.

Modification of a volatile object cannot be moved across a sequence
point.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 13 '07 #11
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
"David T. Ashley" <dt*@e3ft.comwrites:
[...]
>OK, fair enough. But is there anything in the standard that says the
compiler can't reorder this:

volatile int x,y;
x = 0;
y = 1;

to

volatile int x,y;
y = 1;
x = 0;
[...]

Yes. C99 6.7.3p6 says:

An object that has volatile-qualified type may be modified in ways
unknown to the implementation or have other unknown side
effects. Therefore any expression referring to such an object
shall be evaluated strictly according to the rules of the abstract
machine, as described in 5.1.2.3. Furthermore, at every sequence
point the value last stored in the object shall agree with that
prescribed by the abstract machine, except as modified by the
unknown factors mentioned previously.

Modification of a volatile object cannot be moved across a sequence
point.
Thanks for the great answer.

I suspected that. OK, I can sleep at night again.

There are contexts with volatile objects where the order above makes a
difference. It makes sense that things can't be shuffled beyond sequence
points.

In my mind at least, the property addressed by the above is different than
my mental notion of volatile.

My mental notion of volatile is "can change separate from the thread being
compiled".

My next mental notion of volatile is "a read or write cycle might have other
effects than it would with memory, i.e. reading it once might be different
than reading it twice".

But the property I'm speaking of is "co-volatility", where volatile objects
are interdependent ... the sequence point restriction seems to address that.
Jan 13 '07 #12

Harald van Dijk wrote:
loic-...@gmx.net wrote:
Hello everybody!

Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();

It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.
Does that mean if a break point is set at line L3, it could be possible
that *done = 1 and routine is not called yet ? Debugging such a
program (instruction reordered) would be a pain. Any suggestions on how
to debug such programs ?
Also, do you think this is an incorrect way of coding ? if yes, then
what should be the best way to code such scenarios ?

Jan 13 '07 #13
ju**********@yahoo.co.in wrote:
Harald van Dijk wrote:
loic-...@gmx.net wrote:
Hello everybody!
>
Assume that I have the following function:
>
void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}
>
Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();
It is allowed to do that if and only if it can know that the behaviour
for both sequences is the same. So if it doesn't know whether routine
can access *done, it can't reorder the statements.

Does that mean if a break point is set at line L3, it could be possible
that *done = 1 and routine is not called yet ?
Yes.
Debugging such a
program (instruction reordered) would be a pain. Any suggestions on how
to debug such programs ?
Use a compiler-specific option to disable this reordering. Or, if your
compiler and debugger make this available, look at the (hopefully
annotated) assembly code.
Also, do you think this is an incorrect way of coding ? if yes, then
what should be the best way to code such scenarios ?
Incorrect? Depending on how it's used, I might move the variable and
the check into the routine itself, but it may not always be an option.
Even when it is an option, it's nothing more than that, the code as
given would function just as well.

Jan 13 '07 #14
<ju**********@yahoo.co.inwrote in message
news:11**********************@a75g2000cwd.googlegr oups.com...
Does that mean if a break point is set at line L3, it could be
possible
that *done = 1 and routine is not called yet ? Debugging such a
program (instruction reordered) would be a pain. Any suggestions on
how to debug such programs ?
Virtually anything is possible, provided the resulting program still
obeys the "as if" rule. Optimizing compilers do all sorts of strange
and wonderful things to your code to make it run faster, and for complex
code you'd need to be very familar with assembly coding to be able to
figure out what the heck the output is doing and why. Since this is
what the debugger has to work with, it can be downright confusing trying
to correlate anything at that level with the original source if
optimizations are used.

For this reason, it's best to thoroughly check the program for
correctness, including any necessary trips through the debugger, without
any optimization enabled. Then, when you're reasonably sure the code is
correct, you kick up the compiler's optimization level and verify it's
still behaving correctly. Odds are it will, but now and then you'll
find things that weren't actually correct but weren't exposed in the
unoptimized code for some reason. Very, very rarely you'll find a bug
in the optimizations; I've found exactly one in GCC in over a decade of
coding, and it had already been fixed in a later release than I was
using at the time.
Also, do you think this is an incorrect way of coding ? if yes, then
what should be the best way to code such scenarios ?
This is a pretty simple example, and I doubt any compiler will manage to
improve it much; it'd probably still be recognizable at the highest
optimization levels. Most compilers don't bother trying to optimize
across procedure boundaries, and even those that do will likely be
stymied by calling a function that's passed in as an argument. And,
when they can't prove an optimization is "safe", they have to fall back
to actually emitting code that does what you said to do and how you said
to do it.

As noted elsewhere in the thread, the "volatile" keyword is an explicit
notification to the compiler that many (most?) optimizations aren't
"safe" when the designated variables are involved. At least, that's how
I think of how compilers interpret it; the standard is more precise but
IMHO less clear.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
--
Posted via a free Usenet account from http://www.teranews.com

Jan 13 '07 #15
Hello,
Assume that I have the following function:

void
call_once(int* done, void(*routine)(void))
{
if (!(*done)) { /* L1 */
routine(); /* L2 */
*done = 1; /* L3 */
}
}

Is an ANSI C compliant compiler authorized to re-order L2 and L3, i.e.
execute the following sequence instead:
*done = 1;
routine();
Thanks everybody for your interesting replies. Since the restrict
keyword hasn't been used for the prototype, and since the compiler does
not know anything about the routine() function when call_once() is
compiled, it follows that re-ordering cannot occur in this case.

Thanks again and enjoy!
Loic.

Jan 14 '07 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Hayko Riemenschneider | last post by:
Hi! I've got me an XSL tranformation stylesheet for my XML file. In the XSL file I now wish to use PHP to do some scripting. So I thought I'll use the PIs like this: ...
3
by: Trogdor | last post by:
I set up a server on an AMD 650 machine running gentoo linux. I installed Apachie 2, MySQL 4.1 and PHP 4.3.11 I use another computer on my local net (192.168.0.x) to access the server as a...
4
by: Vincent Lefevre | last post by:
How can I get the list of the processing-instruction names in a file? I tried the Muenchian method; it works on the element names for instance, but if I replace * by processing-instruction() to...
3
by: Phil | last post by:
Hi everybody, I am a XSLT beginner and the following problem really makes me crazy ! I have a main "contacts.xml" document which contains references to several contact data XML files. My aim...
3
by: ilcario | last post by:
I would like access to direct addess port via Giveio.sys device driver (with windows xp e 2k). i don't understand why this source for pilot a uart controller tra an exception in _asm cli...
1
by: Chery | last post by:
I used dataset to merge 2 XML files having the same structure. I managed to merge these 2 XML files but how can I write a processing instruction to link the merged file to the existing XSL...
2
by: ledder77 | last post by:
Hi, I need to find a way to insert a processing instruction to an xml document after all the other nodes have been correctly added. That's because I get an xml from a method that I can't modify...
2
by: Jean Stax | last post by:
Hi ! I am looking for a way to call IL instruction from withing C# code. I am not talking about System.Reflection.Emit sort of topics, but rather about existing C# code, where I want to call IL...
13
by: NISARG | last post by:
Hi, is there any single instruction or operator in 'C' to convert a byte such that MSB will become LSB and so..... for example:11101010 will become 01010111 it can be done by building a...
3
by: weird0 | last post by:
i am trying to add nodes to a node dynamically ... and assign its proerties to a node objects stored inside the array.... when the ShapeAdded event is fired... ...inside the if block... ...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.