Boost logo

Boost Users :

Subject: [Boost-users] [Thread] Not able to compile a program with Thread library on ARM
From: Rudi Dittrich (rudid_at_[hidden])
Date: 2008-09-24 09:53:59


Dear all,

I've got the following problem: I want to use the boost threading library provided in version 1.36 on an arm (imx31) based evaluation board with MontaVista linux and g++ version 4.2.0 on it.
When I try to compile the following example with my arm-g++ compiler

#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>

class Worker
{
private:
    int _id; ///< The id of the worker.

public:
    Worker( int id ) : _id( id ) {}

    // Is the function that is called when this worker is started.
        // Doesn't do anything usefull.
    void run()
    {
        for (unsigned int i=0; i<30000000; i++);
    }
};
typedef boost::shared_ptr<Worker> worker_ptr;
typedef std::vector<worker_ptr> worker_vec;

// Starts worker threads.
void run( int nr_workers )
{
    worker_vec workers( nr_workers );
    boost::thread_group tg;

    for (int i = 0; i < nr_workers; i++) {
        worker_ptr w( new Worker(i) );
        workers[i] = w;
        tg.create_thread( boost::bind( &Worker::run, w ) );
    }

    tg.join_all();
}

int main( int argc, char *argv[] )
{
    int worker_nr = 5;
    run( worker_nr );
    return 0;
}

I get the following error message:

/opt/montavista/mobilinux/devkit/arm/v6_vfp_le/lib/gcc/armv6fl-montavista-linux-gnueabi/4.2.0/../../../../armv6fl-montavista-linux-gnueabi/bin/ld: thread-test: hidden symbol `__sync_add_and_fetch_4' in /opt/montavista/mobilinux/devkit/arm/v6_vfp_le/lib/gcc/armv6fl-montavista-linux-gnueabi/4.2.0/libgcc.a(linux-atomic.o) is referenced by DSO
/opt/montavista/mobilinux/devkit/arm/v6_vfp_le/lib/gcc/armv6fl-montavista-linux-gnueabi/4.2.0/../../../../armv6fl-montavista-linux-gnueabi/bin/ld: final link failed: Nonrepresentable section on output
collect2: ld returned 1 exit status

I do not get any linking errors while compiling it on my PC, so may be there is missing something?

I've read in "http://lists.boost.org/Archives/boost/2007/09/127103.php " that this problems comes from the fact that
__sync__fetch_and_add(&x,1) , which is needed by shared_pointers, is not implemented in gcc for ARM.

So according to the problem stated above I've two questions:
- Does there already exist a workaround which solves the problem mentioned above?
- I have added a new header file (atomic_count_arm.hpp) to the boost/detail directory. It implements the atomic_count
  class with specific arm inline assemply instructions in the operator overloads functions.

#ifndef BOOST_DETAIL_ATOMIC_COUNT_ARM_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_ARM_HPP_INCLUDED

namespace boost
{

namespace detail
{

class atomic_count
{
public:

    explicit atomic_count( long v ) : value_( v ) {}

    void operator++()
    {
                long tmp;
                int result;

                   __asm__ __volatile__(
                        "1: ldrex %0, [%2]\n"
                        " add %0, %0, #1\n"
                        " strex %1, %0, [%2]\n"
                        " cmp %1, #0\n"
                        " bne 1b"
                        : "=&r"(tmp), "=&r"(result) // output parameters
                        : "r"(&value_) // input parameters
                        : "memory", "cc" // clobbers
                );
        }

    long operator--()
    {
                long tmp;
                int result;

                    __asm__ __volatile__(
                        "1: ldrex %0, [%2]\n"
                        " add %0, %0, #-1\n"
                        " strex %1, %0, [%2]\n"
                        " cmp %1, #0\n"
                        " bne 1b"
                        : "=&r"(tmp), "=&r"(result) // output parameters
                        : "r"(&value_) // input parameters
                        : "memory", "cc" // clobbers
                );
    }

    operator long() const
    {
                long tmp;
                int result;
            
                __asm__ __volatile__(
                        "1: ldrex %0, [%2]\n"
                        " strex %1, %0, [%2]\n"
                        " cmp %1, #0\n"
                        " bne 1b"
                        : "=&r"(tmp), "=&r"(result) // output parameters
                        : "r"(&value_) // input parameters
                        : "cc" // clobbers
                );

                return tmp;
        }

private:

    atomic_count(atomic_count const &);
    atomic_count & operator=(atomic_count const &);

    mutable long value_;
};

} // namespace detail

} // namespace boost

#endif

  Further I've added the following lines into atomic_count.hpp:
  #elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && defined( __arm__ )
  #include <boost/detail/atomic_count_arm.hpp>

 and before:
 #elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
 # include <boost/detail/atomic_count_sync.hpp>

 Then I recompiled boost and the threading example given above and suprise, it compiles. I'm also able to
 execute the test-program.
 So, do you think that this is feasable solution?

Best regards,

Rudi Dittrich

-- 
GMX startet ShortView.de. Hier findest Du Leute mit Deinen Interessen!
Jetzt dabei sein: http://www.shortview.de/wasistshortview.php?mc=sv_ext_mf@gmx

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net