1

I have some C++ code that uses a local-scope, program-lifetime object, e.g.

void testFunction(int arg) {
   static Tested tested(0);
   tested.use(arg);
}

which built fine with older versions of GCC. With GCC 8.2.0, I get a puzzling warning at link time:

warning: legacy compatible __sync_synchronize used. Not suitable for multi-threaded applications

It points the line defining tested, and indeed there is a call to __sync_synchronize() that has been generated by the compiler. I guess it is there to ensure that no two threads could run the initializing code at the same time and have the lazy initialization produce the same result as if there was load-time initialization.

Issue is reproduced with this implementation of the Tested class:

class Tested {
  int sum;
public:
  Tested(int init) : sum(init) {}
  void use(int arg) {
    sum += arg;
  }
  int current() const {
    return sum;
  }
};

This code is expected to run on a mono-thread embedded platform.

Am I right believing that the warning is not relevant for me ?

What can I do (beside stopping using the static object) to get rid of the warning message ?

PypeBros
  • 2,607
  • 24
  • 37
  • 1
    [MCVE] please. What is `Tested`? Certainly function-statics are still expected to work overall. – Lightness Races in Orbit Jan 02 '19 at 16:51
  • 1
    Code doesn't even compile due to this `void testFunction(arg)`. Once fixed, [norepro with GCC 8.1](http://coliru.stacked-crooked.com/a/638fe03b3046da53) but you did say it started in 8.2. Have you looked on Bugzilla? Bear in mind [8.2.0 indicates a development/trunk build](https://gcc.gnu.org/develop.html), not a real, specific version. Have you tried with [the actual releases 8.2.1 or 8.2.2](https://www.gnu.org/software/gcc/gcc-8/)? – Lightness Races in Orbit Jan 02 '19 at 17:04
  • I noted something pretty suspicious in https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/patches/newlib-3.0.0.patch that I'm using to link this. Apparently that's the non-GNU library that has no support for this function despite the compiler write code that calls it. – PypeBros Jan 02 '19 at 17:06
  • I really don't know where you want us to look in that 8289-line (!) file – Lightness Races in Orbit Jan 02 '19 at 17:08
  • sorry. https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/patches/newlib-3.0.0.patch#L7945 line 7945 has a match for the "legacy ..." error message. – PypeBros Jan 02 '19 at 17:09
  • just tried with g++-8 package from ubuntu LTS. did not reproduced. Suggests that the issue is indeed with the devkitpro flavour of newlib rather than with GNU ld itself. – PypeBros Jan 02 '19 at 17:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/186060/discussion-between-pypebros-and-lightness-races-in-orbit). – PypeBros Jan 02 '19 at 17:23
  • 1
    @LightnessRacesinOrbit you have it exactly backwards, 8.2.0 is an official release. 8.1.0 is the first release from the 8.x branch, 8.2.0 is the second. And 8.2.1 is an unreleased snapshot from the gcc-8-branch some time after 8.2.0 and before 8.3.0 – Jonathan Wakely Jan 14 '19 at 10:46
  • @JonathanWakely Interesting - have I always been wrong on that or has version policy changed? I always thought x.y.0 was a placeholder for pre-release trunk builds in GCC, and that x.y.1 was the first real release. Could be I'm thinking of x.0.z? _(edit: [yes, I am](https://gcc.gnu.org/develop.html))_ – Lightness Races in Orbit Jan 14 '19 at 10:48
  • @JonathanWakely Either way thanks for the correction - that suggests there is either a bug in what turns out to be a real release 8.2.0 or something else is afoot. – Lightness Races in Orbit Jan 14 '19 at 10:49
  • 1
    @LightnessRacesinOrbit you've always been wrong on that. It's been that way since the new [numbering scheme](https://gcc.gnu.org/develop.html#num_scheme) introduced with gcc 5, and was completely different before (there was no part of the x.y.z number that distinguished "release" vs "snapshot", that's the benefit of the new scheme). x.0.0 is a trunk build, x.0.1 is a pre-release shortly after trunk branches for a new release, and the scheme doesn't permit x.0.z with z > 1. – Jonathan Wakely Jan 14 '19 at 10:52
  • @JonathanWakely Cool cool. FWIW, I like the scheme, even if I don't always remember it accurately ;) – Lightness Races in Orbit Jan 14 '19 at 10:55
  • 1
    @LightnessRacesinOrbit It's not a bug, no. It's simply a toolchain that supports armv4t and multithreading for other platforms. OP is slightly confused. – WinterMute Jan 14 '19 at 14:47
  • @WinterMute Got it. I have learned this from Jonathan's answer! – Lightness Races in Orbit Jan 14 '19 at 14:48
  • @WinterMute, any chance multithreading was enabled "recently" on that toolchain ? (e.g. to support Switch development ?) – PypeBros Jan 14 '19 at 14:53
  • @PypeBros No. Switch uses devkitA64, not devkitARM. Recent gcc versions comply with newer standards. – WinterMute Jan 15 '19 at 15:08

2 Answers2

5

You're getting a linker warning, generated by that version of newlib, to tell you that your application has calls to __sync_synchronize and that there is no implementation of that function that actually synchronizes. The implementation of that function in newlib is a stub that does nothing (it probably just exists to ensure there are no undefined references to that function).

Those calls probably come from within libstdc++.so, as GCC on ARM will emit calls to __sync_synchronize for some atomic operations that happen inside the library (e.g. reference count updates in std::string or shared_ptr objects).

To get a working __sync_synchronize that makes the atomics correct you probably need to link to libatomic (using -latomic) which will have an implementation of that function. Because you aren't linking to that, you get the fallback stub implementation in newlib. If you don't need synchronized atomics (because your application is single-threaded and never tries to update atomics in signal handlers) then I think you can ignore the warning.

Another option would be to use a build of libstdc++.so that explicitly disables all threading, and in theory that wouldn't have any references to __sync_synchronize. But that build of libstdc++.so could only ever be used for single-threaded applications. The build you're using now can be used for both single-threaded and multi-threaded code (even if you get this warning that isn't very relevant for single-threaded cases).

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
-2

It would have been better for you to wait on a reply at https://devkitpro.org/viewtopic.php?f=13&t=8822#p16213 rather than asking on a site where most people aren't familiar with devkitARM.

tl;dr; compile your code with -fno-threadsafe-statics & don't worry about it.

WinterMute
  • 336
  • 3
  • 5