LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 28024 - ppc64 (be and le) don't have a working std::call_once
Summary: ppc64 (be and le) don't have a working std::call_once
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Core LLVM classes (show other bugs)
Version: trunk
Hardware: PC All
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-06-06 13:41 PDT by Chandler Carruth
Modified: 2020-08-27 14:00 PDT (History)
10 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chandler Carruth 2016-06-06 13:41:45 PDT
This appears to be a bug in the libstdc++ implementation of std::call_once, but it may be somewhat specific to ABI issues as there are differences between stage1 and stage2 in LE.

Here are the build bot builds that started failing when I landed r271800 that switch LLVM to use std::call_once on various implementations:
http://lab.llvm.org:8011/builders/clang-ppc64le-linux-multistage/builds/1169
http://lab.llvm.org:8011/builders/clang-ppc64be-linux-multistage/builds/2703

These fail in unit tests that use INITIALIZE_PASS which defines a function that uses std::call_once. The failure happens when the implementation of std::call_once throws std::system_error with the '-1' return of a call to pthread_once. I don't know why pthread_once would fail here. I've tried to reproduce any failure to properly initialize the std::once_flag (which contains as a member the pthread_once_t variable passed to pthread_once) but to no avail on my system.

Hopefully someone who works on PPC can figure this out.

Also, when I tried to disable this in r271821, it worked for ppc64le, and for stage2 in ppc64be, but not for stage1 for some reason! Really weird:
http://lab.llvm.org:8011/builders/clang-ppc64be-linux-multistage/builds/2707

Again, I can't figure out how or why this would happen. Hopefully some PPC folks can figure this out.
Comment 1 Bill Seurer 2016-06-06 14:22:06 PDT
I tried the macros on ppc64be:

seurer@hogun:~/test/macro$ cat t.C
#if defined(LLVM_ON_UNIX) &&                                                   \
    !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__ppc__)
#define LLVM_THREADING_USE_STD_CALL_ONCE 1
#error LLVM_THREADING_USE_STD_CALL_ONCE was set to 1
#else
#define LLVM_THREADING_USE_STD_CALL_ONCE 0
#error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
#endif

seurer@hogun:~/test/macro$ ~buildbots/ppc64be-clang-test/clang-ppc64be/stage1/bin/clang++ -c t.C
t.C:7:2: error: LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
#error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
 ^
1 error generated.
seurer@hogun:~/test/macro$ ~/gcc/install/gcc-5.3.0/bin/g++ -c t.C
t.C:7:2: error: #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
 #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
  ^
Comment 2 Chandler Carruth 2016-06-06 14:41:24 PDT
(In reply to comment #1)
> I tried the macros on ppc64be:
> 
> seurer@hogun:~/test/macro$ cat t.C
> #if defined(LLVM_ON_UNIX) &&                                                
> \
>     !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__ppc__)
> #define LLVM_THREADING_USE_STD_CALL_ONCE 1
> #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 1
> #else
> #define LLVM_THREADING_USE_STD_CALL_ONCE 0
> #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
> #endif
> 
> seurer@hogun:~/test/macro$
> ~buildbots/ppc64be-clang-test/clang-ppc64be/stage1/bin/clang++ -c t.C
> t.C:7:2: error: LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
> #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
>  ^
> 1 error generated.
> seurer@hogun:~/test/macro$ ~/gcc/install/gcc-5.3.0/bin/g++ -c t.C
> t.C:7:2: error: #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
>  #error LLVM_THREADING_USE_STD_CALL_ONCE was set to 0
>   ^

I mean, this is what I would expect.

But given that, I can't explain the failure shown in the ppc64be build 2707 where it really seems to be throwing std::system_error out of the implementation of std::call_once.
Comment 3 Chandler Carruth 2016-06-14 12:15:59 PDT
So, any progress here? the BE build bot has been red for over a week at this point.
Comment 4 Bill Seurer 2016-06-14 17:25:25 PDT
__ppc__ is not set on powerpc (at least not by the compiler).  You should use __powerpc__ instead.

When I looked at the preprocessor output of Threading.h LLVM_THREADING_USE_STD_CALL_ONCE is set to 1 because LLVM_ON_UNIX is also defined.  In my little test it was not of course.  Sorry that that caused confusion.

I tried changing Threading.h locally to this

#if defined(LLVM_ON_UNIX) &&                                                   \
    !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__powerpc__)
#define LLVM_THREADING_USE_STD_CALL_ONCE 1
#else
#define LLVM_THREADING_USE_STD_CALL_ONCE 0
#endif

So the #else will be what is used.  When I built and ran the tests they all worked.

The tests also work if I do not build with -DBUILD_SHARED_LIBS=ON even without changing Threading.h.
Comment 5 Chandler Carruth 2016-06-14 17:41:02 PDT
(In reply to comment #4)
> __ppc__ is not set on powerpc (at least not by the compiler).  You should
> use __powerpc__ instead.

So, I can change to __powerpc__, but I'm not really sure that's the right fix... You see, __ppc__ seems just as canonical as __powerpc__. For example this document suggests them equally:
https://sourceforge.net/p/predef/wiki/Architectures/

And if you check the output of Clang itself, it defines both.

And on the LE build bot, __ppc__ seems to work.

So while we can change this, I suspect that roughly no one else in the world is aware that there exist some variants of toolchain and architecture that fail to define __ppc__ but do define __powerpc__. My personal suggestion would be to fix the compiler that omits __ppc__, but I'm also happy for you to try to update all the documentation and such to make it clear what the canonical macro should be.

> 
> When I looked at the preprocessor output of Threading.h
> LLVM_THREADING_USE_STD_CALL_ONCE is set to 1 because LLVM_ON_UNIX is also
> defined.  In my little test it was not of course.  Sorry that that caused
> confusion.
> 
> I tried changing Threading.h locally to this
> 
> #if defined(LLVM_ON_UNIX) &&                                                
> \
>     !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) &&
> !defined(__powerpc__)
> #define LLVM_THREADING_USE_STD_CALL_ONCE 1
> #else
> #define LLVM_THREADING_USE_STD_CALL_ONCE 0
> #endif
> 
> So the #else will be what is used.  When I built and ran the tests they all
> worked.

Yes, that removes the confusion between the two build bots.

But this bug is not about that. This bug is that I think PPC should not be checked here because it should have a working std::call_once implementation, and yet using the std;:call_once implementation causes pthread_once to fail. And more worrisomely it fails in different stages between the BE and LE build bot, and as you point out below, it starts working when using shared libraries.

So there is some bug either in the PPC std::call_once implementation, or in the generated code by Clang for that implementation on PPC. That is what this bug is about.

Essentially, you should be able to delete the "!defined(__powerpc__)" (or "!defined(__ppc__)" as it is currently spelled, and things *should* work, and the fact that they don't is a bug.

> 
> The tests also work if I do not build with -DBUILD_SHARED_LIBS=ON even
> without changing Threading.h.
Comment 6 Bill Seurer 2016-06-14 18:06:23 PDT
From trying them out none of gcc 4.8, 4.9, 5.3, 6, nor 7 define __ppc__ on either BE or LE.  clang though does.

The ELFv2 ABI (Power Architecture 64-bit ELF V2 ABI Specification, OpenPOWER ABI for Linux Supplement) in Section 5.1.4, "Predefined Macros" shows that the defines are:

__PPC__, __powerpc__, __PPC64__, __powerpc64__

The sourceforge.net document is in error.

So it would appear that on LE the new code you added works and it is only on BE that it fails and the old way needs to be used until it is figured out what is wrong.
Comment 7 Chandler Carruth 2016-06-14 18:08:17 PDT
(In reply to comment #6)
> From trying them out none of gcc 4.8, 4.9, 5.3, 6, nor 7 define __ppc__ on
> either BE or LE.  clang though does.
> 
> The ELFv2 ABI (Power Architecture 64-bit ELF V2 ABI Specification, OpenPOWER
> ABI for Linux Supplement) in Section 5.1.4, "Predefined Macros" shows that
> the defines are:
> 
> __PPC__, __powerpc__, __PPC64__, __powerpc64__
> 
> The sourceforge.net document is in error.

Nice! glad that the spec actually calls out stuff here, that helps make it more clear.

> 
> So it would appear that on LE the new code you added works and it is only on
> BE that it fails and the old way needs to be used until it is figured out
> what is wrong.

Hah, not quite. Because it only was failing on LE during *stage 2*. But at that point, we're using Clang, and clang defines __ppc__...
Comment 8 Chandler Carruth 2016-06-14 18:08:49 PDT
(In reply to comment #7)
> (In reply to comment #6)
> > From trying them out none of gcc 4.8, 4.9, 5.3, 6, nor 7 define __ppc__ on
> > either BE or LE.  clang though does.
> > 
> > The ELFv2 ABI (Power Architecture 64-bit ELF V2 ABI Specification, OpenPOWER
> > ABI for Linux Supplement) in Section 5.1.4, "Predefined Macros" shows that
> > the defines are:
> > 
> > __PPC__, __powerpc__, __PPC64__, __powerpc64__
> > 
> > The sourceforge.net document is in error.
> 
> Nice! glad that the spec actually calls out stuff here, that helps make it
> more clear.
> 
> > 
> > So it would appear that on LE the new code you added works and it is only on
> > BE that it fails and the old way needs to be used until it is figured out
> > what is wrong.
> 
> Hah, not quite. Because it only was failing on LE during *stage 2*. But at
> that point, we're using Clang, and clang defines __ppc__...

(Also, wow, thanks for digging into this. My surprise is at how complex this is! I really appreciate you looking at what's going wrong here.)
Comment 9 Chandler Carruth 2016-06-14 18:09:08 PDT
(In reply to comment #7)
> (In reply to comment #6)
> > From trying them out none of gcc 4.8, 4.9, 5.3, 6, nor 7 define __ppc__ on
> > either BE or LE.  clang though does.
> > 
> > The ELFv2 ABI (Power Architecture 64-bit ELF V2 ABI Specification, OpenPOWER
> > ABI for Linux Supplement) in Section 5.1.4, "Predefined Macros" shows that
> > the defines are:
> > 
> > __PPC__, __powerpc__, __PPC64__, __powerpc64__
> > 
> > The sourceforge.net document is in error.
> 
> Nice! glad that the spec actually calls out stuff here, that helps make it
> more clear.
> 
> > 
> > So it would appear that on LE the new code you added works and it is only on
> > BE that it fails and the old way needs to be used until it is figured out
> > what is wrong.
> 
> Hah, not quite. Because it only was failing on LE during *stage 2*. But at
> that point, we're using Clang, and clang defines __ppc__...

(Also, wow, thanks for digging into this. My surprise is at how complex this is! I really appreciate you looking at what's going wrong here.)
Comment 10 Eric Christopher 2016-06-14 18:11:29 PDT
(For fun btw there's this bit in gcc/config/rs6000/darwin.h:

  if (!TARGET_64BIT) builtin_define ("__ppc__");    \

so it'll get defined, but only for 32-bit there :)
Comment 11 cycheng 2016-06-14 21:48:15 PDT
(In reply to comment #7)
> (In reply to comment #6)
> Hah, not quite. Because it only was failing on LE during *stage 2*. But at
> that point, we're using Clang, and clang defines __ppc__...

My testing on PPC64-LE system showed that it was even failing in *stage 1*, if I
build llvm/clang with -DBUILD_SHARED_LIBS=on.

If I build with -DBUILD_SHARED_LIBS=off, then there were no failings in any stage.
Comment 12 Nemanja Ivanovic 2018-08-08 06:38:17 PDT
This issue seems to have resurfaced in another thread. Should we change Threading.h as follows:

Index: include/llvm/Support/Threading.h
===================================================================
--- include/llvm/Support/Threading.h    (revision 338649)
+++ include/llvm/Support/Threading.h    (working copy)
@@ -27,7 +27,7 @@
 #define LLVM_THREADING_USE_STD_CALL_ONCE 1
 #elif defined(LLVM_ON_UNIX) &&                                                 \
     (defined(_LIBCPP_VERSION) ||                                               \
-     !(defined(__NetBSD__) || defined(__OpenBSD__) || defined(__ppc__)))
+     !(defined(__NetBSD__) || defined(__OpenBSD__) || defined(__PPC__)))
 // std::call_once from libc++ is used on all Unix platforms. Other
 // implementations like libstdc++ are known to have problems on NetBSD,
 // OpenBSD and PowerPC.
Comment 13 Brad Smith 2020-08-27 14:00:46 PDT
Fixed quite awhile ago with 9b5fce1ce9af3b19101381bd0f9719f6ff35f709.