Discussion:
__sync_sychronize on ARM
Jon Masters
2012-01-30 06:56:41 UTC
Permalink
Greetings,

I have been trying to help diagnose a failure to build in the icu
package for Fedora on ARM systems, with gcc 4.7. I should very much like
to know the answer to a few questions, so that I can help fix this. I
would like to say at the outset that I believe I am a reasonably
competent programmer, but I am not (yet perhaps) a gcc hacker, though I
certainly enjoy any such opportunity to get to know its internals more.
I understand more of the theory than the implementation of compilers :)

The __sync_synchronize "legacy" sync function is intended to be used to
perform an expensive data memory barrier operation. It is defined within
libgcc in such a way that I *believe* means that, on most architectures,
it is replaced with an inline assembly code emitted that performs a sync
operation. On ARM, and some other architectures with mixed ISAs wherein
there may not be a sync function nor one way to do this, this function
(__sync_synchronize) can be a real function call. In that case, it might
cause inline assembly generation, or e.g. call a kernel VDSO helper.

The icu package contains a direct call to __sync_sychronize, especially
in the iotest test cases. I believe that this compiles fine on x86
because there is no function call. However, on ARM, the code fails to
link because the __sync_synchronize function is HIDDEN and not exported
(or so goes my understanding - is that correct?). I am drawing a blank,
though, on how this differs from earlier versions of gcc such as 4.6
(aside from a slight difference in the macro used to make it available),
and whether it is indeed the case that this function should be made
available within libgcc for direct linking? In other words, I do not
know whether there is a bug here in gcc or whether icu needs changing.
It seems that there are newer, less expensive sync operations that
perhaps ought to be used instead, but I don't have the full context.

Please forgive my lack of understanding of gcc intrinsics, and atomics.
I would very much like to learn more about the internal implementation
and I look forward to whatever information you can share with me. If you
would like more information, I can happily provide it in the morning. It
is very late here, but I wanted to start this thread asap. We are trying
to fix icu so that we can continue to build Fedora 17 for ARM systems.

Thanks very much,

Jon.
Ramana Radhakrishnan
2012-01-30 08:50:43 UTC
Permalink
Post by Jon Masters
The __sync_synchronize "legacy" sync function is intended to be used to
perform an expensive data memory barrier operation. It is defined within
libgcc in such a way that I *believe* means that, on most architectures,
it is replaced with an inline assembly code emitted that performs a sync
operation. On ARM, and some other architectures with mixed ISAs wherein
there may not be a sync function nor one way to do this, this function
(__sync_synchronize) can be a real function call. In that case, it might
cause inline assembly generation, or e.g. call a kernel VDSO helper.
On ARM we don't have a kernel VDSO , sync_synchronize for older versions of
the architecture ( anything prior to armv6k) should result in a call
to sync_synchronize
in libgcc.a which should take care of calling the kernel helper function.

Therefore I'm assuming this is a breakage you face when building for armv5te
Post by Jon Masters
The icu package contains a direct call to __sync_sychronize, especially
in the iotest test cases. I believe that this compiles fine on x86
because there is no function call. However, on ARM, the code fails to
link because the __sync_synchronize function is HIDDEN and not exported
(or so goes my understanding - is that correct?).
No, the HIDDEN shouldn't cause a link failure in this case - you
should be able to pull this
in when you link against the static libgcc where this should be defined.

I don't know what your linker command line is so maybe that's a place
to start investigating from.


cheers
Ramana
Jon Masters
2012-01-30 17:26:38 UTC
Permalink
Hi Ramana,

Thanks very much for getting back to me!
Post by Ramana Radhakrishnan
Post by Jon Masters
The __sync_synchronize "legacy" sync function is intended to be used to
perform an expensive data memory barrier operation. It is defined within
libgcc in such a way that I *believe* means that, on most architectures,
it is replaced with an inline assembly code emitted that performs a sync
operation. On ARM, and some other architectures with mixed ISAs wherein
there may not be a sync function nor one way to do this, this function
(__sync_synchronize) can be a real function call. In that case, it might
cause inline assembly generation, or e.g. call a kernel VDSO helper.
On ARM we don't have a kernel VDSO
You're right of course! I was confusing the VDSO-like user mode mapped
helpers (Documentation/arm/kernel_user_helpers.txt) with full VDSO. I
apologize for my mistake. Nonetheless, I believe for the purposes of
this thread, we can consider the behavior I described roughly consistent
with reality, because a kernel helper will be called in a VDSO-like way.
Post by Ramana Radhakrishnan
sync_synchronize for older versions of
the architecture ( anything prior to armv6k) should result in a call
to sync_synchronize
in libgcc.a which should take care of calling the kernel helper function.
This is what's confusing me :) Is one supposed (from some random source)
to be calling __sync_synchronize or sync_synchronize? Convention
suggests the latter, but I was sufficiently confused by the aliasing of
the names in the source vs. the documentation, so I'd like to ask you :)
Post by Ramana Radhakrishnan
Therefore I'm assuming this is a breakage you face when building for armv5te
It is indeed. Thanks for noting that.
Post by Ramana Radhakrishnan
Post by Jon Masters
The icu package contains a direct call to __sync_sychronize, especially
in the iotest test cases. I believe that this compiles fine on x86
because there is no function call. However, on ARM, the code fails to
link because the __sync_synchronize function is HIDDEN and not exported
(or so goes my understanding - is that correct?).
No, the HIDDEN shouldn't cause a link failure in this case - you
should be able to pull this
in when you link against the static libgcc where this should be defined.
I don't know what your linker command line is so maybe that's a place
to start investigating from.
Thanks! You're the second person to suggest that, so I'll look some
more. Could you let me know about the correct function name, above?

Appreciate the help.

Jon.
Andrew Haley
2012-01-30 17:45:51 UTC
Permalink
Post by Jon Masters
Post by Ramana Radhakrishnan
Therefore I'm assuming this is a breakage you face when building for armv5te
It is indeed. Thanks for noting that.
Post by Ramana Radhakrishnan
Post by Jon Masters
The icu package contains a direct call to __sync_sychronize, especially
in the iotest test cases. I believe that this compiles fine on x86
because there is no function call. However, on ARM, the code fails to
link because the __sync_synchronize function is HIDDEN and not exported
(or so goes my understanding - is that correct?).
No, the HIDDEN shouldn't cause a link failure in this case - you
should be able to pull this
in when you link against the static libgcc where this should be defined.
I don't know what your linker command line is so maybe that's a place
to start investigating from.
There has been a bug in the past where
/usr/lib/gcc/armv7hl-redhat-linux-gnueabi/4.6.1/libgcc_s.so was not a
linker script, but a shared library or a symlink. That bug definitely
would cause the problem you're seeing.

libgcc_s.so must be a script.

You can get a linker map with the option -Wl,-Map,mapfile
This would be very useful.
Post by Jon Masters
Thanks! You're the second person to suggest that, so I'll look some
more. Could you let me know about the correct function name, above?
The official documented builtin is __sync_synchronize ()

Andrew.
Jon Masters
2012-01-30 21:20:17 UTC
Permalink
Hello everyone,

Just a quick followup. This problem is now resolved. There is no
breakage in gcc, just a problem in the Fedora icu package. That package
contains some sed scripts in the "SPEC" (build description meta) file
that intentionally were munging the Makefiles used to build ICU such
that "nostdlib" was being given to gcc and it was never using libgcc.

The intention of the person who made this change apparently was to
prevent linking the standard math library into icu, but unfortunately a
rather unusual solution was chosen. On some systems, one can almost get
away with this because __sync_synchronize happens to be implemented in
such a fashion that it is optimized into inline emitted assembly. On
ARM, that isn't the case. In addition, it is likely that telling GCC not
to link in core libraries like libgcc will lead to other breakage later.

I have requested the package be fixed to remove the sed scripts and have
temporarily (just to solve our problem in the Fedora ARM community) had
"-lgcc" added to the linker flags as a very hackish solution for today.

Thanks for the replies, and I apologize for the noise. I have learned a
great deal about gcc atomics over the past few days. I have also learned
that debugging packages requires that you build the package *exactly* as
it is in the spec file, not just by running configure/make as therein ;)

Jon.

Loading...