amazing optimization

Hi, I have a very strange problem.
I wrote to function which are shown below:

void
datas_server_ocb_free (datas_server_ocb_t *tocb)
{
remove_pid_hash_entry(tocb->client_pid);
free (tocb);
}


void remove_pid_hash_entry(pid_t pid){
Tcl_HashEntry *hash_entry_p = NULL;
pid_hash_t *pid_hash = NULL;

/* printf("%d\n", pid); */
hash_entry_p = Tcl_FindHashEntry(pid_hash_table, (char *)pid);
if (hash_entry_p != NULL) {
pid_hash = Tcl_GetHashValue(hash_entry_p);
free(pid_hash);
Tcl_DeleteHashEntry(hash_entry_p);
}

}

In the remove_pid_hash_entry() function I don’t get the pid value but the
tocb address!

If I enable the printf function, the problem disappear!
Maybe gcc gets confused here by the (char *) but elswhere in my code, that
works well.
What to do to prevent that?

Thanks,
Alain.

Alain Bonnefoy wrote:

In the remove_pid_hash_entry() function I don’t get the pid value but the
tocb address!

It sounds as if you are getting stack corruption somewhere. It is certain that
the ocb address is on the stack from the call to datas_server_ocb_free. Calling
printf alters the stack arrangement.

Have you stepped through this code with the debugger (with the printf removed) ?
You might be able to get a better idea of what is happening using a slightly
less intrusive debugger…

If I enable the printf function, the problem disappear!
Maybe gcc gets confused here by the (char *) but elswhere in my code, that
works well.
What to do to prevent that?

There is nothing wrong with casting an int to a pointer to char, as long as any
code using the result doesn’t actually dereference it (a process id is very
unlikely to coincide with useful address within your process).

“Rennie Allen” <rgallen@attbi.com> wrote in message
news:c2ssit$b5d$1@inn.qnx.com

There is nothing wrong with casting an int to a pointer to char, as long
as any
code using the result doesn’t actually dereference it (a process id is
very
unlikely to coincide with useful address within your process).

Yes there is. You’re not guaranteed that casting from an int fits in a
char*.


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

Well, you are right Adam but I don’t think that’s my problem here.
I’m also agree with Rennie about stack arrangement but in that way, that’s
strange.
I add a local variable in the called function to just make a test against
the pid parameter and again, That solve my problem.
I think that shows there is not a problem with stack arrangement because
AFAIR parameters are stacked before the return address while local
parameters are stacked after.

So, adding a:

pid_t tmp_pid = pid; <----- HERE pid is good already according to ddd.
if (tmp_pid != pid){assert(tmp_pid != pid)};

doesn’t change anything to the pid position in the stack (no push, no call,
no return, no pop) and we see that there is no problem to access the
parameter in that circumstance.
Anyway with or without this line, that changes the way to access it. I
didn’t check the machine code (I’m not really familiar with x86 asm code
:frowning: I will see on monday) but I really don’t understand what is the problem.

I’m still thinking there is something in the context of that block of code
which make gcc to imagine a ‘better’ way to do what it understand about my
code.

Thanks, Alain.

“Adam Mallory” <amallory@qnx.com> a écrit dans le message de
news:c2t089$e3s$1@inn.qnx.com

“Rennie Allen” <> rgallen@attbi.com> > wrote in message
news:c2ssit$b5d$> 1@inn.qnx.com> …

There is nothing wrong with casting an int to a pointer to char, as long
as any
code using the result doesn’t actually dereference it (a process id is
very
unlikely to coincide with useful address within your process).

Yes there is. You’re not guaranteed that casting from an int fits in a
char*.


Cheers,
Adam

QNX Software Systems Ltd.
[ > amallory@qnx.com > ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <> pschon@baste.magibox.net

Alain Bonnefoy <bonnefoy@club-internet.fr> wrote:
AB > Well, you are right Adam but I don’t think that’s my problem here.
AB > I’m also agree with Rennie about stack arrangement but in that way, that’s
AB > strange.
AB > I add a local variable in the called function to just make a test against
AB > the pid parameter and again, That solve my problem.
AB > I think that shows there is not a problem with stack arrangement because
AB > AFAIR parameters are stacked before the return address while local
AB > parameters are stacked after.

AB > So, adding a:

AB > pid_t tmp_pid = pid; <----- HERE pid is good already according to ddd.
AB > if (tmp_pid != pid){assert(tmp_pid != pid)};

AB > doesn’t change anything to the pid position in the stack (no push, no call,
AB > no return, no pop) and we see that there is no problem to access the
AB > parameter in that circumstance.
AB > Anyway with or without this line, that changes the way to access it. I
AB > didn’t check the machine code (I’m not really familiar with x86 asm code
AB > :frowning: I will see on monday) but I really don’t understand what is the problem.

AB > I’m still thinking there is something in the context of that block of code
AB > which make gcc to imagine a ‘better’ way to do what it understand about my
AB > code.

AB > Thanks, Alain.

Just for fun, try compiling with all optimizations turned off.
If the exact same code works with no optimizations and doesn’t work
with optimizations, then you found a bug in the compiler. Try to post
the asm code generated by both with and without optimizations.

Someone here can figure something out.

Compiler bugs can be the most frustrating to deal with. We generally
consider the compiler a trusted tool. Fools that we are.

“Bill Caroselli” <qtps@earthlink.net> wrote in message
news:c2t6sg$iti$3@inn.qnx.com

Alain Bonnefoy <> bonnefoy@club-internet.fr> > wrote:
AB > Well, you are right Adam but I don’t think that’s my problem here.
AB > I’m also agree with Rennie about stack arrangement but in that way,
that’s
AB > strange.
AB > I add a local variable in the called function to just make a test
against
AB > the pid parameter and again, That solve my problem.
AB > I think that shows there is not a problem with stack arrangement
because
AB > AFAIR parameters are stacked before the return address while local
AB > parameters are stacked after.

AB > So, adding a:

AB > pid_t tmp_pid = pid; <----- HERE pid is good already according to
ddd.
AB > if (tmp_pid != pid){assert(tmp_pid != pid)};

AB > doesn’t change anything to the pid position in the stack (no push, no
call,
AB > no return, no pop) and we see that there is no problem to access the
AB > parameter in that circumstance.
AB > Anyway with or without this line, that changes the way to access it.
I
AB > didn’t check the machine code (I’m not really familiar with x86 asm
code
AB > > :frowning: > I will see on monday) but I really don’t understand what is the
problem.

AB > I’m still thinking there is something in the context of that block of
code
AB > which make gcc to imagine a ‘better’ way to do what it understand
about my
AB > code.

AB > Thanks, Alain.

Just for fun, try compiling with all optimizations turned off.
If the exact same code works with no optimizations and doesn’t work
with optimizations, then you found a bug in the compiler. Try to post
the asm code generated by both with and without optimizations.

I agree that optimizations are a likely culprit, and aliasing optimizations
would be prime amongst those, except that it doesn’t fit the normal
criteria for allowing aliases, unless the function declaration doesn’t
match the definition.

These were relatively common in the QNX4/Watcom days, because
Watcom could be very aggressive about pointer aliasing to global storage.
It worked great if you were careful about usage, but not so well
if you did lots of unsafe casting through pointers.

This would especially account for differences related to local expressions
using the variable, because it can increase the complexity of validating
whether
the optimization can be applied.

For example, if the variable appears in any l-value expression, it isn’t
valid to alias references inside the function to values in some other
scope. This should be extremely rare (in fact, I don’t see any suggestion
that GCC envisions it as a code-gen possibility) in any case other than a
pointer to a
global or static, unless the compiler had very particular call graph
information
(static storage class functions in particular).

These functions must be in the same translation unit though, right?

The optimizer may not attempt to be very clever about which
expressions disable such an optimization, but if it tries to, it
could discount r-values and apply dead code elimination first.
If that were to happen, only a meaningful use of the value, like
calling a var-args function, say, might disable it. (“int p = pid;”
might not eliminate the error).

Go to progressively lower optimizations – or work the other way – to
determine when it starts working. Then look at the set of optimizations
applicable at the offending level. You can then turn off
suspect optimizations – to the extent that GCC allows it –
to pinpoint the culprit. Don’t bother with obvious non-candidates
(like loop un-rolling, etc.).


Someone here can figure something out.

Compiler bugs can be the most frustrating to deal with. We generally
consider the compiler a trusted tool. Fools that we are.

Adam Mallory wrote:

“Rennie Allen” <> rgallen@attbi.com> > wrote in message
Yes there is. You’re not guaranteed that casting from an int fits in a
char*.

True; but for every machine QNX runs on, an int always fits into a pointer
does it not ? Since this is clearly resmgr code, I don’t foresee any
requirements for portability.

“Rennie Allen” <rallen@csical.com> wrote in message
news:405620DD.4040205@csical.com

True; but for every machine QNX runs on, an int always fits into a pointer
does it not ? Since this is clearly resmgr code, I don’t foresee any
requirements for portability.

It’s not just about size of the containers, it’s about representation.
You’re assuming that an int cast to a char* and then back into an int is
going to yeild the same value you started with.


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

Adam Mallory wrote:

“Rennie Allen” <> rallen@csical.com> > wrote in message
news:> 405620DD.4040205@csical.com> …


True; but for every machine QNX runs on, an int always fits into a pointer
does it not ? Since this is clearly resmgr code, I don’t foresee any
requirements for portability.


It’s not just about size of the containers, it’s about representation.
You’re assuming that an int cast to a char* and then back into an int is
going to yeild the same value you started with.

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

Thanks,

Rennie

Hi,
Strictly speaking, you are right but I think that’s not the problem here.
The value is used as a hash table key. Depending on the table
initialization, it could a pointer or a simple double word value. I hope gcc
doesn’t make any assumption on it. Elsewhere in the code, that works fine.

So, based on your answer and the bill’s one, I made some tries and it seems
that there is a problem with optimization.
Declaring a local variable getting my parameter’s value has the same effect
as removing the optimization.

So, This is the C source code:

void remove_pid_hash_entry(volatile pid_t pid){
Tcl_HashEntry *hash_entry_p = NULL;
pid_hash_t pid_hash = NULL;
pid_t itself = pid;
/
Don’t remove this stupid line!! This is because of it the program works!!
*/

hash_entry_p = Tcl_FindHashEntry(pid_hash_table, (char *)pid);
if (hash_entry_p != NULL) {
pid_hash = Tcl_GetHashValue(hash_entry_p);
free(pid_hash);
Tcl_DeleteHashEntry(hash_entry_p);
}

}

If I comment ‘pid_t itself = pid;’ and compile with optimization, the
resulting asm is:

0x804b860 <remove_pid_hash_entry>: push %ebp
0x804b861 <remove_pid_hash_entry+1>: mov %esp,%ebp
0x804b863 <remove_pid_hash_entry+3>: sub $0x14,%esp
0x804b866 <remove_pid_hash_entry+6>: push %ebx
0x804b867 <remove_pid_hash_entry+7>: add $0xfffffff8,%esp
0x804b86a <remove_pid_hash_entry+10>: mov 0x806090c,%eax
0x804b86f <remove_pid_hash_entry+15>: mov 0x8(%ebp),%edx
0x804b872 <remove_pid_hash_entry+18>: push %edx
0x804b873 <remove_pid_hash_entry+19>: push %eax
0x804b874 <remove_pid_hash_entry+20>: mov 0x2c(%eax),%eax
0x804b877 <remove_pid_hash_entry+23>: call *%eax
0x804b879 <remove_pid_hash_entry+25>: mov %eax,%ebx
0x804b87b <remove_pid_hash_entry+27>: add $0x10,%esp
0x804b87e <remove_pid_hash_entry+30>: test %ebx,%ebx
0x804b880 <remove_pid_hash_entry+32>: je 0x804b896
<remove_pid_hash_entry+54>
0x804b882 <remove_pid_hash_entry+34>: add $0xfffffff4,%esp
0x804b885 <remove_pid_hash_entry+37>: pushl 0xc(%ebx)
0x804b888 <remove_pid_hash_entry+40>: call 0x804a01c
0x804b88d <remove_pid_hash_entry+45>: add $0xfffffff4,%esp
0x804b890 <remove_pid_hash_entry+48>: push %ebx
0x804b891 <remove_pid_hash_entry+49>: call 0x8049c8c
<Tcl_DeleteHashEntry>
0x804b896 <remove_pid_hash_entry+54>: mov 0xffffffe8(%ebp),%ebx
0x804b899 <remove_pid_hash_entry+57>: leave
0x804b89a <remove_pid_hash_entry+58>: ret

If I compile the same code without optimization (only for that file, others
are not rebuilt), the resulting asm is:

0x804bc33 <remove_pidd_hash_entry+7>: movl $0x0,0xfffffffc(%ebp)
0x804bc46 <remove_pid_hash_entry+14>: movl $0x0,0xfffffff8(%ebp)
0x804bc4d <remove_pid_hash_entry+21>: mov 0x8(%ebp),%eax
0x804bc50 <remove_pid_hash_entry+24>: mov %eax,0xfffffff4(%ebp)
0x804bc53 <remove_pid_hash_entry+27>: add $0xfffffff8,%esp
0x804bc56 <remove_pid_hash_entry+30>: mov 0x8062c2c,%eax
0x804bc5b <remove_pid_hash_entry+35>: mov 0x8(%ebp),%edx
0x804bc5e <remove_pid_hash_entry+38>: push %edx
0x804bc5f <remove_pid_hash_entry+39>: mov 0x8062c2c,%edx
0x804bc65 <remove_pid_hash_entry+45>: push %edx
0x804bc66 <remove_pid_hash_entry+46>: mov 0x2c(%eax),%ebx
0x804bc69 <remove_pid_hash_entry+49>: call *%ebx
0x804bc6b <remove_pid_hash_entry+51>: add $0x10,%esp
0x804bc6e <remove_pid_hash_entry+54>: mov %eax,%eax
0x804bc70 <remove_pid_hash_entry+56>: mov %eax,0xfffffffc(%ebp)
0x804bc73 <remove_pid_hash_entry+59>: cmpl $0x0,0xfffffffc(%ebp)
0x804bc77 <remove_pid_hash_entry+63>: je 0x804bca0
<remove_pid_hash_entry+104>
0x804bc79 <remove_pid_hash_entry+65>: mov 0xfffffffc(%ebp),%eax
0x804bc7c <remove_pid_hash_entry+68>: mov 0xc(%eax),%edx
0x804bc7f <remove_pid_hash_entry+71>: mov %edx,0xfffffff8(%ebp)
0x804bc82 <remove_pid_hash_entry+74>: add $0xfffffff4,%esp
0x804bc85 <remove_pid_hash_entry+77>: mov 0xfffffff8(%ebp),%eax
0x804bc88 <remove_pid_hash_entry+80>: push %eax
0x804bc89 <remove_pid_hash_entry+81>: call 0x804a01c
0x804bc8e <remove_pid_hash_entry+86>: add $0x10,%esp
0x804bc91 <remove_pid_hash_entry+89>: add $0xfffffff4,%esp
0x804bc94 <remove_pid_hash_entry+92>: mov 0xfffffffc(%ebp),%eax
0x804bc97 <remove_pid_hash_entry+95>: push %eax
0x804bc98 <remove_pid_hash_entry+96>: call 0x8049c8c
<Tcl_DeleteHashEntry>
0x804bc9d <remove_pid_hash_entry+101>: add $0x10,%esp
0x804bca0 <remove_pid_hash_entry+104>: mov 0xffffffe8(%ebp),%ebx
0x804bca3 <remove_pid_hash_entry+107>: leave
0x804bca4 <remove_pid_hash_entry+108>: ret


If not I compile with optimization but with ‘pid_t itself = pid’ enabled,
the resulting asm code is:

0x804b860 <remove_pid_hash_entry>: push %ebp
0x804b861 <remove_pid_hash_entry+1>: mov %esp,%ebp
0x804b863 <remove_pid_hash_entry+3>: sub $0x14,%esp
0x804b866 <remove_pid_hash_entry+6>: push %ebx
0x804b867 <remove_pid_hash_entry+7>: mov 0x8(%ebp),%eax
0x804b86a <remove_pid_hash_entry+10>: add $0xfffffff8,%esp
0x804b86d <remove_pid_hash_entry+13>: mov 0x806090c,%edx
0x804b873 <remove_pid_hash_entry+19>: mov 0x8(%ebp),%eax
0x804b876 <remove_pid_hash_entry+22>: push %eax
0x804b877 <remove_pid_hash_entry+23>: push %edx
0x804b878 <remove_pid_hash_entry+24>: mov 0x2c(%edx),%eax
0x804b87b <remove_pid_hash_entry+27>: call *%eax
0x804b87d <remove_pid_hash_entry+29>: mov %eax,%ebx
0x804b87f <remove_pid_hash_entry+31>: add $0x10,%esp
0x804b882 <remove_pid_hash_entry+34>: test %ebx,%ebx
0x804b884 <remove_pid_hash_entry+36>: je 0x804b89a
<remove_pid_hash_entry+58>
0x804b886 <remove_pid_hash_entry+38>: add $0xfffffff4,%esp
0x804b889 <remove_pid_hash_entry+41>: pushl 0xc(%ebx)
0x804b88c <remove_pid_hash_entry+44>: call 0x804a01c
0x804b891 <remove_pid_hash_entry+49>: add $0xfffffff4,%esp
0x804b894 <remove_pid_hash_entry+52>: push %ebx
0x804b895 <remove_pid_hash_entry+53>: call 0x8049c8c
<Tcl_DeleteHashEntry>
0x804b89a <remove_pid_hash_entry+58>: mov 0xffffffe8(%ebp),%ebx
0x804b89d <remove_pid_hash_entry+61>: leave
0x804b89e <remove_pid_hash_entry+62>: ret

In fact, I’m not really familiar with the asm code, but it seems that the
local variable is absent which could be confirmed the warning message
‘unused variable ‘itself’’.
But the way to access the parameter is a bit different compare to the first
asm dump. Right?

What do you think about that?

regards,
Alain.


“Rennie Allen” <rgallen@attbi.com> a écrit dans le message de news:
c35vlt$odm$1@inn.qnx.com

Adam Mallory wrote:
“Rennie Allen” <> rallen@csical.com> > wrote in message
news:> 405620DD.4040205@csical.com> …


True; but for every machine QNX runs on, an int always fits into a
pointer
does it not ? Since this is clearly resmgr code, I don’t foresee any
requirements for portability.


It’s not just about size of the containers, it’s about representation.
You’re assuming that an int cast to a char* and then back into an int is
going to yeild the same value you started with.

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

Thanks,

Rennie

No, there must be something else going on (not an optimization
problem). Your first and third asm outputs are effectively
identical. The roles of EAX and EDX are interchanged in the
first few instructions, and the “‘pid_t itself = pid;’ enabled”
case has a redundant “mov 0x8(%ebp),%eax”, but there are no
significant differences (that I can see, anyway).

What key type did you tell the initialization routine (presumably
Tcl_InitHashTable or Tcl_InitCustomHashTable), by the way?

dB


“Alain Bonnefoy” wrote ~ Tue, 16 Mar 2004 10:18:54 +0100:

Hi,
Strictly speaking, you are right but I think that’s not the problem here.
The value is used as a hash table key. Depending on the table
initialization, it could a pointer or a simple double word value. I hope gcc
doesn’t make any assumption on it. Elsewhere in the code, that works fine.

So, based on your answer and the bill’s one, I made some tries and it seems
that there is a problem with optimization.
Declaring a local variable getting my parameter’s value has the same effect
as removing the optimization.

So, This is the C source code:

void remove_pid_hash_entry(volatile pid_t pid){
Tcl_HashEntry *hash_entry_p = NULL;
pid_hash_t pid_hash = NULL;
pid_t itself = pid;
/
Don’t remove this stupid line!! This is because of it the program works!!
*/

hash_entry_p = Tcl_FindHashEntry(pid_hash_table, (char *)pid);
if (hash_entry_p != NULL) {
pid_hash = Tcl_GetHashValue(hash_entry_p);
free(pid_hash);
Tcl_DeleteHashEntry(hash_entry_p);
}

}

If I comment ‘pid_t itself = pid;’ and compile with optimization, the
resulting asm is:

0x804b860 <remove_pid_hash_entry>: push %ebp
0x804b861 <remove_pid_hash_entry+1>: mov %esp,%ebp
0x804b863 <remove_pid_hash_entry+3>: sub $0x14,%esp
0x804b866 <remove_pid_hash_entry+6>: push %ebx
0x804b867 <remove_pid_hash_entry+7>: add $0xfffffff8,%esp
0x804b86a <remove_pid_hash_entry+10>: mov 0x806090c,%eax
0x804b86f <remove_pid_hash_entry+15>: mov 0x8(%ebp),%edx
0x804b872 <remove_pid_hash_entry+18>: push %edx
0x804b873 <remove_pid_hash_entry+19>: push %eax
0x804b874 <remove_pid_hash_entry+20>: mov 0x2c(%eax),%eax
0x804b877 <remove_pid_hash_entry+23>: call *%eax
0x804b879 <remove_pid_hash_entry+25>: mov %eax,%ebx
0x804b87b <remove_pid_hash_entry+27>: add $0x10,%esp
0x804b87e <remove_pid_hash_entry+30>: test %ebx,%ebx
0x804b880 <remove_pid_hash_entry+32>: je 0x804b896
remove_pid_hash_entry+54
0x804b882 <remove_pid_hash_entry+34>: add $0xfffffff4,%esp
0x804b885 <remove_pid_hash_entry+37>: pushl 0xc(%ebx)
0x804b888 <remove_pid_hash_entry+40>: call 0x804a01c <free
0x804b88d <remove_pid_hash_entry+45>: add $0xfffffff4,%esp
0x804b890 <remove_pid_hash_entry+48>: push %ebx
0x804b891 <remove_pid_hash_entry+49>: call 0x8049c8c
Tcl_DeleteHashEntry
0x804b896 <remove_pid_hash_entry+54>: mov 0xffffffe8(%ebp),%ebx
0x804b899 <remove_pid_hash_entry+57>: leave
0x804b89a <remove_pid_hash_entry+58>: ret

If I compile the same code without optimization (only for that file, others
are not rebuilt), the resulting asm is:

0x804bc33 <remove_pidd_hash_entry+7>: movl $0x0,0xfffffffc(%ebp)
0x804bc46 <remove_pid_hash_entry+14>: movl $0x0,0xfffffff8(%ebp)
0x804bc4d <remove_pid_hash_entry+21>: mov 0x8(%ebp),%eax
0x804bc50 <remove_pid_hash_entry+24>: mov %eax,0xfffffff4(%ebp)
0x804bc53 <remove_pid_hash_entry+27>: add $0xfffffff8,%esp
0x804bc56 <remove_pid_hash_entry+30>: mov 0x8062c2c,%eax
0x804bc5b <remove_pid_hash_entry+35>: mov 0x8(%ebp),%edx
0x804bc5e <remove_pid_hash_entry+38>: push %edx
0x804bc5f <remove_pid_hash_entry+39>: mov 0x8062c2c,%edx
0x804bc65 <remove_pid_hash_entry+45>: push %edx
0x804bc66 <remove_pid_hash_entry+46>: mov 0x2c(%eax),%ebx
0x804bc69 <remove_pid_hash_entry+49>: call *%ebx
0x804bc6b <remove_pid_hash_entry+51>: add $0x10,%esp
0x804bc6e <remove_pid_hash_entry+54>: mov %eax,%eax
0x804bc70 <remove_pid_hash_entry+56>: mov %eax,0xfffffffc(%ebp)
0x804bc73 <remove_pid_hash_entry+59>: cmpl $0x0,0xfffffffc(%ebp)
0x804bc77 <remove_pid_hash_entry+63>: je 0x804bca0
remove_pid_hash_entry+104
0x804bc79 <remove_pid_hash_entry+65>: mov 0xfffffffc(%ebp),%eax
0x804bc7c <remove_pid_hash_entry+68>: mov 0xc(%eax),%edx
0x804bc7f <remove_pid_hash_entry+71>: mov %edx,0xfffffff8(%ebp)
0x804bc82 <remove_pid_hash_entry+74>: add $0xfffffff4,%esp
0x804bc85 <remove_pid_hash_entry+77>: mov 0xfffffff8(%ebp),%eax
0x804bc88 <remove_pid_hash_entry+80>: push %eax
0x804bc89 <remove_pid_hash_entry+81>: call 0x804a01c <free
0x804bc8e <remove_pid_hash_entry+86>: add $0x10,%esp
0x804bc91 <remove_pid_hash_entry+89>: add $0xfffffff4,%esp
0x804bc94 <remove_pid_hash_entry+92>: mov 0xfffffffc(%ebp),%eax
0x804bc97 <remove_pid_hash_entry+95>: push %eax
0x804bc98 <remove_pid_hash_entry+96>: call 0x8049c8c
Tcl_DeleteHashEntry
0x804bc9d <remove_pid_hash_entry+101>: add $0x10,%esp
0x804bca0 <remove_pid_hash_entry+104>: mov 0xffffffe8(%ebp),%ebx
0x804bca3 <remove_pid_hash_entry+107>: leave
0x804bca4 <remove_pid_hash_entry+108>: ret


If not I compile with optimization but with ‘pid_t itself = pid’ enabled,
the resulting asm code is:

0x804b860 <remove_pid_hash_entry>: push %ebp
0x804b861 <remove_pid_hash_entry+1>: mov %esp,%ebp
0x804b863 <remove_pid_hash_entry+3>: sub $0x14,%esp
0x804b866 <remove_pid_hash_entry+6>: push %ebx
0x804b867 <remove_pid_hash_entry+7>: mov 0x8(%ebp),%eax
0x804b86a <remove_pid_hash_entry+10>: add $0xfffffff8,%esp
0x804b86d <remove_pid_hash_entry+13>: mov 0x806090c,%edx
0x804b873 <remove_pid_hash_entry+19>: mov 0x8(%ebp),%eax
0x804b876 <remove_pid_hash_entry+22>: push %eax
0x804b877 <remove_pid_hash_entry+23>: push %edx
0x804b878 <remove_pid_hash_entry+24>: mov 0x2c(%edx),%eax
0x804b87b <remove_pid_hash_entry+27>: call *%eax
0x804b87d <remove_pid_hash_entry+29>: mov %eax,%ebx
0x804b87f <remove_pid_hash_entry+31>: add $0x10,%esp
0x804b882 <remove_pid_hash_entry+34>: test %ebx,%ebx
0x804b884 <remove_pid_hash_entry+36>: je 0x804b89a
remove_pid_hash_entry+58
0x804b886 <remove_pid_hash_entry+38>: add $0xfffffff4,%esp
0x804b889 <remove_pid_hash_entry+41>: pushl 0xc(%ebx)
0x804b88c <remove_pid_hash_entry+44>: call 0x804a01c <free
0x804b891 <remove_pid_hash_entry+49>: add $0xfffffff4,%esp
0x804b894 <remove_pid_hash_entry+52>: push %ebx
0x804b895 <remove_pid_hash_entry+53>: call 0x8049c8c
Tcl_DeleteHashEntry
0x804b89a <remove_pid_hash_entry+58>: mov 0xffffffe8(%ebp),%ebx
0x804b89d <remove_pid_hash_entry+61>: leave
0x804b89e <remove_pid_hash_entry+62>: ret

In fact, I’m not really familiar with the asm code, but it seems that the
local variable is absent which could be confirmed the warning message
‘unused variable ‘itself’’.
But the way to access the parameter is a bit different compare to the first
asm dump. Right?

What do you think about that?

regards,
Alain.


“Rennie Allen” <> rgallen@attbi.com> > a écrit dans le message de news:
c35vlt$odm$> 1@inn.qnx.com> …
Adam Mallory wrote:
“Rennie Allen” <> rallen@csical.com> > wrote in message
news:> 405620DD.4040205@csical.com> …


True; but for every machine QNX runs on, an int always fits into a
pointer
does it not ? Since this is clearly resmgr code, I don’t foresee any
requirements for portability.


It’s not just about size of the containers, it’s about representation.
You’re assuming that an int cast to a char* and then back into an int is
going to yeild the same value you started with.

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

Thanks,

Rennie
\

Well, I checked the initialization of the table and it’s good. I’m allmost
sure there is something wrong elsewhere in my code which cause the problem.
Turning off the optimization force gcc to reload the value which mask the
real problem. I cannot believe in a gcc problem!

Thanks to all!
Alain.
“David Bacon” <dbacon@qnx.com> a écrit dans le message de
news:1079446156824.dB@inn.qnx.com

No, there must be something else going on (not an optimization
problem). Your first and third asm outputs are effectively
identical. The roles of EAX and EDX are interchanged in the
first few instructions, and the “‘pid_t itself = pid;’ enabled”
case has a redundant “mov 0x8(%ebp),%eax”, but there are no
significant differences (that I can see, anyway).

What key type did you tell the initialization routine (presumably
Tcl_InitHashTable or Tcl_InitCustomHashTable), by the way?

dB


“Alain Bonnefoy” wrote ~ Tue, 16 Mar 2004 10:18:54 +0100:
Hi,
Strictly speaking, you are right but I think that’s not the problem
here.
The value is used as a hash table key. Depending on the table
initialization, it could a pointer or a simple double word value. I hope
gcc
doesn’t make any assumption on it. Elsewhere in the code, that works
fine.

So, based on your answer and the bill’s one, I made some tries and it
seems
that there is a problem with optimization.
Declaring a local variable getting my parameter’s value has the same
effect
as removing the optimization.

So, This is the C source code:

void remove_pid_hash_entry(volatile pid_t pid){
Tcl_HashEntry *hash_entry_p = NULL;
pid_hash_t pid_hash = NULL;
pid_t itself = pid;
/
Don’t remove this stupid line!! This is because of it the program
works!!
*/

hash_entry_p = Tcl_FindHashEntry(pid_hash_table, (char *)pid);
if (hash_entry_p != NULL) {
pid_hash = Tcl_GetHashValue(hash_entry_p);
free(pid_hash);
Tcl_DeleteHashEntry(hash_entry_p);
}

}

If I comment ‘pid_t itself = pid;’ and compile with optimization, the
resulting asm is:

0x804b860 <remove_pid_hash_entry>: push %ebp
0x804b861 <remove_pid_hash_entry+1>: mov %esp,%ebp
0x804b863 <remove_pid_hash_entry+3>: sub $0x14,%esp
0x804b866 <remove_pid_hash_entry+6>: push %ebx
0x804b867 <remove_pid_hash_entry+7>: add $0xfffffff8,%esp
0x804b86a <remove_pid_hash_entry+10>: mov 0x806090c,%eax
0x804b86f <remove_pid_hash_entry+15>: mov 0x8(%ebp),%edx
0x804b872 <remove_pid_hash_entry+18>: push %edx
0x804b873 <remove_pid_hash_entry+19>: push %eax
0x804b874 <remove_pid_hash_entry+20>: mov 0x2c(%eax),%eax
0x804b877 <remove_pid_hash_entry+23>: call *%eax
0x804b879 <remove_pid_hash_entry+25>: mov %eax,%ebx
0x804b87b <remove_pid_hash_entry+27>: add $0x10,%esp
0x804b87e <remove_pid_hash_entry+30>: test %ebx,%ebx
0x804b880 <remove_pid_hash_entry+32>: je 0x804b896
remove_pid_hash_entry+54
0x804b882 <remove_pid_hash_entry+34>: add $0xfffffff4,%esp
0x804b885 <remove_pid_hash_entry+37>: pushl 0xc(%ebx)
0x804b888 <remove_pid_hash_entry+40>: call 0x804a01c <free
0x804b88d <remove_pid_hash_entry+45>: add $0xfffffff4,%esp
0x804b890 <remove_pid_hash_entry+48>: push %ebx
0x804b891 <remove_pid_hash_entry+49>: call 0x8049c8c
Tcl_DeleteHashEntry
0x804b896 <remove_pid_hash_entry+54>: mov 0xffffffe8(%ebp),%ebx
0x804b899 <remove_pid_hash_entry+57>: leave
0x804b89a <remove_pid_hash_entry+58>: ret

If I compile the same code without optimization (only for that file,
others
are not rebuilt), the resulting asm is:

0x804bc33 <remove_pidd_hash_entry+7>: movl $0x0,0xfffffffc(%ebp)
0x804bc46 <remove_pid_hash_entry+14>: movl $0x0,0xfffffff8(%ebp)
0x804bc4d <remove_pid_hash_entry+21>: mov 0x8(%ebp),%eax
0x804bc50 <remove_pid_hash_entry+24>: mov %eax,0xfffffff4(%ebp)
0x804bc53 <remove_pid_hash_entry+27>: add $0xfffffff8,%esp
0x804bc56 <remove_pid_hash_entry+30>: mov 0x8062c2c,%eax
0x804bc5b <remove_pid_hash_entry+35>: mov 0x8(%ebp),%edx
0x804bc5e <remove_pid_hash_entry+38>: push %edx
0x804bc5f <remove_pid_hash_entry+39>: mov 0x8062c2c,%edx
0x804bc65 <remove_pid_hash_entry+45>: push %edx
0x804bc66 <remove_pid_hash_entry+46>: mov 0x2c(%eax),%ebx
0x804bc69 <remove_pid_hash_entry+49>: call *%ebx
0x804bc6b <remove_pid_hash_entry+51>: add $0x10,%esp
0x804bc6e <remove_pid_hash_entry+54>: mov %eax,%eax
0x804bc70 <remove_pid_hash_entry+56>: mov %eax,0xfffffffc(%ebp)
0x804bc73 <remove_pid_hash_entry+59>: cmpl $0x0,0xfffffffc(%ebp)
0x804bc77 <remove_pid_hash_entry+63>: je 0x804bca0
remove_pid_hash_entry+104
0x804bc79 <remove_pid_hash_entry+65>: mov 0xfffffffc(%ebp),%eax
0x804bc7c <remove_pid_hash_entry+68>: mov 0xc(%eax),%edx
0x804bc7f <remove_pid_hash_entry+71>: mov %edx,0xfffffff8(%ebp)
0x804bc82 <remove_pid_hash_entry+74>: add $0xfffffff4,%esp
0x804bc85 <remove_pid_hash_entry+77>: mov 0xfffffff8(%ebp),%eax
0x804bc88 <remove_pid_hash_entry+80>: push %eax
0x804bc89 <remove_pid_hash_entry+81>: call 0x804a01c <free
0x804bc8e <remove_pid_hash_entry+86>: add $0x10,%esp
0x804bc91 <remove_pid_hash_entry+89>: add $0xfffffff4,%esp
0x804bc94 <remove_pid_hash_entry+92>: mov 0xfffffffc(%ebp),%eax
0x804bc97 <remove_pid_hash_entry+95>: push %eax
0x804bc98 <remove_pid_hash_entry+96>: call 0x8049c8c
Tcl_DeleteHashEntry
0x804bc9d <remove_pid_hash_entry+101>: add $0x10,%esp
0x804bca0 <remove_pid_hash_entry+104>: mov 0xffffffe8(%ebp),%ebx
0x804bca3 <remove_pid_hash_entry+107>: leave
0x804bca4 <remove_pid_hash_entry+108>: ret


If not I compile with optimization but with ‘pid_t itself = pid’
enabled,
the resulting asm code is:

0x804b860 <remove_pid_hash_entry>: push %ebp
0x804b861 <remove_pid_hash_entry+1>: mov %esp,%ebp
0x804b863 <remove_pid_hash_entry+3>: sub $0x14,%esp
0x804b866 <remove_pid_hash_entry+6>: push %ebx
0x804b867 <remove_pid_hash_entry+7>: mov 0x8(%ebp),%eax
0x804b86a <remove_pid_hash_entry+10>: add $0xfffffff8,%esp
0x804b86d <remove_pid_hash_entry+13>: mov 0x806090c,%edx
0x804b873 <remove_pid_hash_entry+19>: mov 0x8(%ebp),%eax
0x804b876 <remove_pid_hash_entry+22>: push %eax
0x804b877 <remove_pid_hash_entry+23>: push %edx
0x804b878 <remove_pid_hash_entry+24>: mov 0x2c(%edx),%eax
0x804b87b <remove_pid_hash_entry+27>: call *%eax
0x804b87d <remove_pid_hash_entry+29>: mov %eax,%ebx
0x804b87f <remove_pid_hash_entry+31>: add $0x10,%esp
0x804b882 <remove_pid_hash_entry+34>: test %ebx,%ebx
0x804b884 <remove_pid_hash_entry+36>: je 0x804b89a
remove_pid_hash_entry+58
0x804b886 <remove_pid_hash_entry+38>: add $0xfffffff4,%esp
0x804b889 <remove_pid_hash_entry+41>: pushl 0xc(%ebx)
0x804b88c <remove_pid_hash_entry+44>: call 0x804a01c <free
0x804b891 <remove_pid_hash_entry+49>: add $0xfffffff4,%esp
0x804b894 <remove_pid_hash_entry+52>: push %ebx
0x804b895 <remove_pid_hash_entry+53>: call 0x8049c8c
Tcl_DeleteHashEntry
0x804b89a <remove_pid_hash_entry+58>: mov 0xffffffe8(%ebp),%ebx
0x804b89d <remove_pid_hash_entry+61>: leave
0x804b89e <remove_pid_hash_entry+62>: ret

In fact, I’m not really familiar with the asm code, but it seems that
the
local variable is absent which could be confirmed the warning message
‘unused variable ‘itself’’.
But the way to access the parameter is a bit different compare to the
first
asm dump. Right?

What do you think about that?

regards,
Alain.


“Rennie Allen” <> rgallen@attbi.com> > a écrit dans le message de news:
c35vlt$odm$> 1@inn.qnx.com> …
Adam Mallory wrote:
“Rennie Allen” <> rallen@csical.com> > wrote in message
news:> 405620DD.4040205@csical.com> …


True; but for every machine QNX runs on, an int always fits into a
pointer
does it not ? Since this is clearly resmgr code, I don’t foresee
any
requirements for portability.


It’s not just about size of the containers, it’s about
representation.
You’re assuming that an int cast to a char* and then back into an
int is
going to yeild the same value you started with.

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

Thanks,

Rennie
\

Adam Mallory <amallory@qnx.com> wrote:

“Rennie Allen” <> rgallen@attbi.com> > wrote in message
news:c35vlt$odm$> 1@inn.qnx.com> …

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

It’s not about platform - it’s about compiler implementation. The compiler
determines the behaviour of converting an int into a char*. If you ever
change compilers (different vendor, or even different version), you could be
in for a nasty surprise.

On top of that, if the representation doesn’t fit, it’s undefined
behaviour - and the compiler is free to do whatever it wants (including
formating your harddrive > :wink: > ). At the present, I can’t think of a platform
where an int and a pointer are not the same size (ie 32bits), but it’s not
hard to see that could change in the very near future.

AS/400 – granted, not a supported QNX platform…

Cheers,
-RK


[If replying via email, you’ll need to click on the URL that’s emailed to you
afterwards to forward the email to me – spam filters and all that]
Robert Krten, PDP minicomputer collector http://www.parse.com/~pdp8/

“Rennie Allen” <rgallen@attbi.com> wrote in message
news:c35vlt$odm$1@inn.qnx.com

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

It’s not about platform - it’s about compiler implementation. The compiler
determines the behaviour of converting an int into a char*. If you ever
change compilers (different vendor, or even different version), you could be
in for a nasty surprise.

On top of that, if the representation doesn’t fit, it’s undefined
behaviour - and the compiler is free to do whatever it wants (including
formating your harddrive :wink: ). At the present, I can’t think of a platform
where an int and a pointer are not the same size (ie 32bits), but it’s not
hard to see that could change in the very near future.


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

“Robert Krten” <rk@parse.com> wrote in message
news:c379tq$3l7$1@inn.qnx.com

AS/400 – granted, not a supported QNX platform…

Right, but like Rennie had said QNX platform.


Cheers,
Adam

QNX Software Systems Ltd.
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

Adam Mallory <amallory@qnx.com> wrote:

AM > On top of that, if the representation doesn’t fit, it’s undefined
AM > behaviour - and the compiler is free to do whatever it wants (including
AM > formating your harddrive :wink: ).

I heard that some Microsoft compilers will send an e-mail addressed
to your grandmother with you as the return address, and the e-mail is
full of porn !

So, don’t assign ints to char*s or grandma will get pissed at you !

Alain Bonnefoy wrote:

Well, I checked the initialization of the table and it’s good. I’m allmost
sure there is something wrong elsewhere in my code which cause the problem.
Turning off the optimization force gcc to reload the value which mask the
real problem. I cannot believe in a gcc problem!

I would check stack corruption. You don’t have profiling enabled by any

chance. I had some bad stack corruption a couple of weeks back, with
profiling enabled…

“Adam Mallory” <amallory@qnx.com> wrote in message
news:c377m9$1h3$1@inn.qnx.com

“Rennie Allen” <> rgallen@attbi.com> > wrote in message
news:c35vlt$odm$> 1@inn.qnx.com> …

So for which QNX platform is it true that an int cast to a char* and
back does not yield the same value ? PowerPC in little endian mode?
Are addresses a different endianess than data ?

Not that I am going to write code depending on a transparent
int->char*->int, (I won’t say I never have, but I can’t recall ever
doing so) but I’m curious…

It’s not about platform - it’s about compiler implementation. The
compiler
determines the behaviour of converting an int into a char*. If you ever
change compilers (different vendor, or even different version), you could
be
in for a nasty surprise.

On top of that, if the representation doesn’t fit, it’s undefined
behaviour - and the compiler is free to do whatever it wants (including
formating your harddrive > :wink: > ). At the present, I can’t think of a
platform
where an int and a pointer are not the same size (ie 32bits), but it’s not
hard to see that could change in the very near future.

AMD64 and i86e (I think that’s how Intel calls their 64 bit implementation).
But it’s hard to see that supported in the near future under QNX :wink:


Cheers,
Adam

QNX Software Systems Ltd.
[ > amallory@qnx.com > ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <> pschon@baste.magibox.net

“Bill Caroselli” <qtps@earthlink.net> wrote in message
news:c37im4$am1$1@inn.qnx.com

Adam Mallory <> amallory@qnx.com> > wrote:

AM > On top of that, if the representation doesn’t fit, it’s undefined
AM > behaviour - and the compiler is free to do whatever it wants
(including
AM > formating your harddrive > :wink: > ).

I heard that some Microsoft compilers will send an e-mail addressed
to your grandmother with you as the return address, and the e-mail is
full of porn !

So, don’t assign ints to char*s or

grandma will get pissed at you !

Depends on the grandmother

  • Mario

Mario Charest wrote:

AMD64 and i86e (I think that’s how Intel calls their 64 bit implementation).
But it’s hard to see that supported in the near future under QNX > :wink:

Are you referring to the Athlon64 ? IIRC it has a 32 bit code address, 64 bit
data address, and a 64 bit word size. If I am right, then pointers to data
should still be equal to the size of an integer (address size == word size)
(although a pointer to a function would be a different size than an int).

The basic point is that I said Alain is safe in what he is doing (in the
context that he was doing it - he was asking about a very specific piece of
code that he supplied). I still stand by the statement it should work
reliably in the given context (i.e. QNX 6.2.1 gcc 2.95).