Example #1
0
        bool add_new_always(std::size_t& added, thread_queue* addfrom,
            std::unique_lock<mutex_type> &lk, bool steal = false)
        {
            HPX_ASSERT(lk.owns_lock());

#ifdef HPX_HAVE_THREAD_CREATION_AND_CLEANUP_RATES
            util::tick_counter tc(add_new_time_);
#endif

            if (0 == addfrom->new_tasks_count_.load(boost::memory_order_relaxed))
                return false;

            // create new threads from pending tasks (if appropriate)
            boost::int64_t add_count = -1;                  // default is no constraint

            // if we are desperate (no work in the queues), add some even if the
            // map holds more than max_count
            if (HPX_LIKELY(max_count_)) {
                std::size_t count = thread_map_.size();
                if (max_count_ >= count + min_add_new_count) { //-V104
                    HPX_ASSERT(max_count_ - count <
                        static_cast<std::size_t>((std::numeric_limits
                            <boost::int64_t>::max)()));
                    add_count = static_cast<boost::int64_t>(max_count_ - count);
                    if (add_count < min_add_new_count)
                        add_count = min_add_new_count;
                    if (add_count > max_add_new_count)
                        add_count = max_add_new_count;
                }
                else if (work_items_.empty()) {
                    add_count = min_add_new_count;    // add this number of threads
                    max_count_ += min_add_new_count;  // increase max_count //-V101
                }
                else {
                    return false;
                }
            }

            std::size_t addednew = add_new(add_count, addfrom, lk, steal);
            added += addednew;
            return addednew != 0;
        }
Example #2
0
        bool add_new_if_possible(std::size_t& added, thread_queue* addfrom,
            std::unique_lock<mutex_type> &lk, bool steal = false)
        {
            HPX_ASSERT(lk.owns_lock());

#ifdef HPX_HAVE_THREAD_CREATION_AND_CLEANUP_RATES
            util::tick_counter tc(add_new_time_);
#endif

            if (0 == addfrom->new_tasks_count_.load(boost::memory_order_relaxed))
                return false;

            // create new threads from pending tasks (if appropriate)
            boost::int64_t add_count = -1;                  // default is no constraint

            // if the map doesn't hold max_count threads yet add some
            // FIXME: why do we have this test? can max_count_ ever be zero?
            if (HPX_LIKELY(max_count_)) {
                std::size_t count = thread_map_.size();
                if (max_count_ >= count + min_add_new_count) { //-V104
                    HPX_ASSERT(max_count_ - count <
                        static_cast<std::size_t>((std::numeric_limits
                            <boost::int64_t>::max)()));
                    add_count = static_cast<boost::int64_t>(max_count_ - count);
                    if (add_count < min_add_new_count)
                        add_count = min_add_new_count;
                }
                else {
                    return false;
                }
            }

            std::size_t addednew = add_new(add_count, addfrom, lk, steal);
            added += addednew;
            return addednew != 0;
        }
Example #3
0
    bool dump_suspended_threads(std::size_t num_thread,
        Map& tm, boost::int64_t& idle_loop_count, bool running)
    {
#ifndef HPX_THREAD_MINIMAL_DEADLOCK_DETECTION
        HPX_UNUSED(tm);
        HPX_UNUSED(idle_loop_count);
        HPX_UNUSED(running); //-V601
        return false;
#else
        if (!minimal_deadlock_detection)
            return false;
        if (HPX_LIKELY(idle_loop_count++ < HPX_IDLE_LOOP_COUNT_MAX))
            return false;

        // reset idle loop count
        idle_loop_count = 0;

        bool result = false;
        bool collect_suspended = true;

        bool logged_headline = false;
        typename Map::const_iterator end = tm.end();
        for (typename Map::const_iterator it = tm.begin(); it != end; ++it)
        {
            threads::thread_data const* thrd = (*it).get();
            threads::thread_state state = thrd->get_state();
            threads::thread_state marked_state = thrd->get_marked_state();

            if (state != marked_state) {
                // log each thread only once
                if (!logged_headline) {
                    if (running) {
                        LTM_(error) //-V128
                            << "Listing suspended threads while queue ("
                            << num_thread << ") is empty:";
                    }
                    else {
                        LHPX_CONSOLE_(hpx::util::logging::level::error) //-V128
                            << "  [TM] Listing suspended threads while queue ("
                            << num_thread << ") is empty:\n";
                    }
                    logged_headline = true;
                }

                if (running) {
                    LTM_(error) << "queue(" << num_thread << "): " //-V128
                                << get_thread_state_name(state)
                                << "(" << std::hex << std::setw(8)
                                    << std::setfill('0') << (*it).get()
                                << "." << std::hex << std::setw(2)
                                    << std::setfill('0') << thrd->get_thread_phase()
                                << "/" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_component_id()
                                << ")"
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
                                << " P" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_parent_thread_id()
#endif
                                << ": " << thrd->get_description()
                                << ": " << thrd->get_lco_description();
                }
                else {
                    LHPX_CONSOLE_(hpx::util::logging::level::error) << "  [TM] " //-V128
                                << "queue(" << num_thread << "): "
                                << get_thread_state_name(state)
                                << "(" << std::hex << std::setw(8)
                                    << std::setfill('0') << (*it).get()
                                << "." << std::hex << std::setw(2)
                                    << std::setfill('0') << thrd->get_thread_phase()
                                << "/" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_component_id()
                                << ")"
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
                                << " P" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_parent_thread_id()
#endif
                                << ": " << thrd->get_description()
                                << ": " << thrd->get_lco_description() << "\n";
                }
                thrd->set_marked_state(state);

                // result should be true if we found only suspended threads
                if (collect_suspended) {
                    switch(state.get_state()) {
                    case threads::suspended:
                        result = true;    // at least one is suspended
                        break;

                    case threads::pending:
                    case threads::active:
                        result = false;   // one is active, no deadlock (yet)
                        collect_suspended = false;
                        break;

                    default:
                        // If the thread is terminated we don't care too much
                        // anymore.
                        break;
                    }
                }
            }
        }
        return result;
#endif
    }