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; }
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; }
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 }