Skip to content
This repository was archived by the owner on May 21, 2024. It is now read-only.

Build failure on RISC-V due missing __atomic_exchange_1 #1427

@ricardosalveti

Description

@ricardosalveti

When trying to build aktualizr 2019.9 for QEMU RISC-V 64:

/home/rsalveti/build/lmp/build-lmp/tmp-lmp/work/riscv64-lmp-linux/aktualizr/1.0+gitAUTOINC+a358242d9a-7/recipe-sysroot-native/usr/bin
/riscv64-lmp-linux/../../libexec/riscv64-lmp-linux/gcc/riscv64-lmp-linux/9.2.0/ld: src/libaktualizr/utilities/CMakeFiles/utilities.di
r/sig_handler.cc.o: in function `std::__atomic_base<bool>::compare_exchange_strong(bool&, bool, std::memory_order, std::memory_order)
':
/usr/include/c++/9.2.0/bits/atomic_base.h:502: undefined reference to `__atomic_compare_exchange_1'
/home/rsalveti/build/lmp/build-lmp/tmp-lmp/work/riscv64-lmp-linux/aktualizr/1.0+gitAUTOINC+a358242d9a-7/recipe-sysroot-native/usr/bin/riscv64-lmp-linux/../../libexec/riscv64-lmp-linux/gcc/riscv64-lmp-linux/9.2.0/ld: src/libaktualizr/utilities/CMakeFiles/utilities.dir/sig_handler.cc.o: in function `boost::log::v2_mt_posix::aux::basic_ostringstreambuf<char, std::char_traits<char>, std::allocator<char> >::length_until_boundary(char const*, unsigned long, unsigned long, boost::integral_constant<bool, true>) const':
/usr/include/boost/log/detail/attachable_sstream_buf.hpp:289: undefined reference to `__atomic_exchange_1'
/home/rsalveti/build/lmp/build-lmp/tmp-lmp/work/riscv64-lmp-linux/aktualizr/1.0+gitAUTOINC+a358242d9a-7/recipe-sysroot-native/usr/bin/riscv64-lmp-linux/../../libexec/riscv64-lmp-linux/gcc/riscv64-lmp-linux/9.2.0/ld: src/libaktualizr/utilities/CMakeFiles/utilities.dir/sig_handler.cc.o: in function `std::basic_streambuf<char, std::char_traits<char> >::getloc() const':
/usr/include/c++/9.2.0/streambuf:234: undefined reference to `__atomic_exchange_1'
collect2: error: ld returned 1 exit status

Looks like this happens because not every atomic operation is currently supported by GCC on RISC-V.

Investigating further I found two possible ways to fix this issue:
1 - Change from atomic to atomic_uint (which is currently supported by gcc 9.2):

diff --git a/src/libaktualizr/utilities/sig_handler.cc b/src/libaktualizr/utilities/sig_handler.cc
index 80699c5b..364b5243 100644
--- a/src/libaktualizr/utilities/sig_handler.cc
+++ b/src/libaktualizr/utilities/sig_handler.cc
@@ -3,12 +3,12 @@

 void signal_handler(int sig) {
   (void)sig;
-  bool v = false;
+  unsigned int v = 0;
   // put true if currently set to false
-  SigHandler::signal_marker_.compare_exchange_strong(v, true);
+  SigHandler::signal_marker_.compare_exchange_strong(v, 1);
 }

-std::atomic<bool> SigHandler::signal_marker_;
+std::atomic_uint SigHandler::signal_marker_;

 SigHandler& SigHandler::get() {
   static SigHandler handler;
@@ -30,7 +30,7 @@ void SigHandler::start(const std::function<void()>& on_signal) {

   polling_thread_ = boost::thread([this, on_signal]() {
     while (true) {
-      bool signal = signal_marker_.exchange(false);
+      auto signal = signal_marker_.exchange(0);

       if (signal) {
         LOG_INFO << "received KILL request";
diff --git a/src/libaktualizr/utilities/sig_handler.h b/src/libaktualizr/utilities/sig_handler.h
index 03a4a5aa..37a26860 100644
--- a/src/libaktualizr/utilities/sig_handler.h
+++ b/src/libaktualizr/utilities/sig_handler.h
@@ -26,7 +26,7 @@ class SigHandler {

   boost::thread polling_thread_;
   bool signal_pending;
-  static std::atomic<bool> signal_marker_;
+  static std::atomic_uint signal_marker_;

   boost::mutex m;
   int masked_secs_;

2 - Link to libatomic as it is known to have all the required atomic operations for RISC-V:

find_library(LIBATOMIC atomic)

diff --git a/src/cert_provider/CMakeLists.txt b/src/cert_provider/CMakeLists.txt
index 21f45513..08492491 100644
--- a/src/cert_provider/CMakeLists.txt
+++ b/src/cert_provider/CMakeLists.txt
@@ -19,6 +19,7 @@ target_link_libraries(aktualizr-cert-provider
     ${CURL_LIBRARIES}
     ${OPENSSL_LIBRARIES}
     ${sodium_LIBRARY_RELEASE}
+    ${LIBATOMIC}
     )

 aktualizr_source_file_checks(main.cc)

Option 1 doesn't require an extra library but this can bite us again in the future, option 2 seems safe but will add an extra library to aktualizr.

Any opinions?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions